Merge "Added support for Calls.FEATURES_VOLTE in call log."
diff --git a/Android.bp b/Android.bp
index e2a4219..1918ad7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -414,6 +414,7 @@
         "libcore-platform-compat-config",
         "services-platform-compat-config",
         "media-provider-platform-compat-config",
+        "services-devicepolicy-platform-compat-config",
     ],
     sdk_version: "core_platform",
 }
@@ -1461,6 +1462,11 @@
             removed_api_file: "api/removed.txt",
             baseline_file: ":public-api-incompatibilities-with-last-released",
         },
+        api_lint: {
+            enabled: true,
+            new_since: ":last-released-public-api",
+            baseline_file: "api/lint-baseline.txt",
+        },
     },
     jdiff_enabled: true,
 }
@@ -1487,6 +1493,11 @@
             removed_api_file: "api/system-removed.txt",
             baseline_file: ":system-api-incompatibilities-with-last-released"
         },
+        api_lint: {
+            enabled: true,
+            new_since: ":last-released-system-api",
+            baseline_file: "api/system-lint-baseline.txt",
+        },
     },
     jdiff_enabled: true,
 }
@@ -1585,4 +1596,25 @@
         "core/java/com/android/internal/util/State.java",
         "core/java/com/android/internal/util/StateMachine.java",
     ],
-}
\ No newline at end of file
+}
+
+filegroup {
+    name: "framework-wifistack-shared-srcs",
+    srcs: [
+        ":framework-annotations",
+        "core/java/android/util/KeyValueListParser.java",
+        "core/java/android/util/LocalLog.java",
+        "core/java/android/util/Rational.java",
+        "core/java/android/util/proto/ProtoStream.java",
+        "core/java/android/util/proto/ProtoOutputStream.java",
+        "core/java/com/android/internal/util/FastXmlSerializer.java",
+        "core/java/com/android/internal/util/HexDump.java",
+        "core/java/com/android/internal/util/IState.java",
+        "core/java/com/android/internal/util/MessageUtils.java",
+        "core/java/com/android/internal/util/Preconditions.java",
+        "core/java/com/android/internal/util/State.java",
+        "core/java/com/android/internal/util/StateMachine.java",
+        "core/java/com/android/internal/util/WakeupMessage.java",
+        "core/java/com/android/internal/util/XmlUtils.java",
+    ],
+}
diff --git a/apct-tests/perftests/autofill/AndroidManifest.xml b/apct-tests/perftests/autofill/AndroidManifest.xml
index 9c8abc3..1e3532b 100644
--- a/apct-tests/perftests/autofill/AndroidManifest.xml
+++ b/apct-tests/perftests/autofill/AndroidManifest.xml
@@ -18,7 +18,7 @@
 
     <application>
         <uses-library android:name="android.test.runner" />
-        <activity android:name="android.perftests.utils.StubActivity">
+        <activity android:name="android.perftests.utils.PerfTestActivity">
           <intent-filter>
             <action android:name="com.android.perftests.core.PERFTEST" />
           </intent-filter>
diff --git a/apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java b/apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java
index 6979f0f..48ce8ab 100644
--- a/apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java
+++ b/apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java
@@ -20,9 +20,9 @@
 
 import android.os.Looper;
 import android.perftests.utils.PerfStatusReporter;
+import android.perftests.utils.PerfTestActivity;
 import android.perftests.utils.SettingsHelper;
 import android.perftests.utils.SettingsStateKeeperRule;
-import android.perftests.utils.StubActivity;
 import android.provider.Settings;
 
 import androidx.test.InstrumentationRegistry;
@@ -46,8 +46,8 @@
                     Settings.Secure.AUTOFILL_SERVICE);
 
     @Rule
-    public ActivityTestRule<StubActivity> mActivityRule =
-            new ActivityTestRule<StubActivity>(StubActivity.class);
+    public ActivityTestRule<PerfTestActivity> mActivityRule =
+            new ActivityTestRule<>(PerfTestActivity.class);
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
@@ -68,7 +68,7 @@
                     Looper.getMainLooper().getThread() == Thread.currentThread());
             assertTrue("We should be running on the main thread",
                     Looper.myLooper() == Looper.getMainLooper());
-            StubActivity activity = mActivityRule.getActivity();
+            PerfTestActivity activity = mActivityRule.getActivity();
             activity.setContentView(mLayoutId);
             onCreate(activity);
         });
@@ -89,9 +89,9 @@
     }
 
     /**
-     * Initializes the {@link StubActivity} after it was launched.
+     * Initializes the {@link PerfTestActivity} after it was launched.
      */
-    protected abstract void onCreate(StubActivity activity);
+    protected abstract void onCreate(PerfTestActivity activity);
 
     /**
      * Uses the {@code settings} binary to set the autofill service.
diff --git a/apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java b/apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java
index 8090826..fb5ea80 100644
--- a/apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java
+++ b/apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java
@@ -20,7 +20,7 @@
 import static android.view.autofill.AutofillManager.AutofillCallback.EVENT_INPUT_SHOWN;
 
 import android.perftests.utils.BenchmarkState;
-import android.perftests.utils.StubActivity;
+import android.perftests.utils.PerfTestActivity;
 import android.view.View;
 import android.widget.EditText;
 
@@ -39,7 +39,7 @@
     }
 
     @Override
-    protected void onCreate(StubActivity activity) {
+    protected void onCreate(PerfTestActivity activity) {
         View root = activity.getWindow().getDecorView();
         mUsername = root.findViewById(R.id.username);
         mPassword = root.findViewById(R.id.password);
diff --git a/apct-tests/perftests/core/AndroidManifest.xml b/apct-tests/perftests/core/AndroidManifest.xml
index 525975d..290f178 100644
--- a/apct-tests/perftests/core/AndroidManifest.xml
+++ b/apct-tests/perftests/core/AndroidManifest.xml
@@ -13,7 +13,7 @@
 
     <application>
         <uses-library android:name="android.test.runner" />
-        <activity android:name="android.perftests.utils.StubActivity">
+        <activity android:name="android.perftests.utils.PerfTestActivity">
           <intent-filter>
             <action android:name="com.android.perftests.core.PERFTEST" />
           </intent-filter>
diff --git a/apct-tests/perftests/core/src/android/app/PendingIntentPerfTest.java b/apct-tests/perftests/core/src/android/app/PendingIntentPerfTest.java
index b3f8359..a320514 100644
--- a/apct-tests/perftests/core/src/android/app/PendingIntentPerfTest.java
+++ b/apct-tests/perftests/core/src/android/app/PendingIntentPerfTest.java
@@ -20,7 +20,7 @@
 import android.content.Intent;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
-import android.perftests.utils.StubActivity;
+import android.perftests.utils.PerfTestActivity;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.LargeTest;
@@ -48,7 +48,7 @@
     @Before
     public void setUp() {
         mContext = InstrumentationRegistry.getTargetContext();
-        mIntent = StubActivity.createLaunchIntent(mContext);
+        mIntent = PerfTestActivity.createLaunchIntent(mContext);
     }
 
     /**
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/PaintHasGlyphPerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/PaintHasGlyphPerfTest.java
index 3a80020..b9c7af4 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/PaintHasGlyphPerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/PaintHasGlyphPerfTest.java
@@ -19,7 +19,7 @@
 import android.graphics.Paint;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
-import android.perftests.utils.StubActivity;
+import android.perftests.utils.PerfTestActivity;
 
 import androidx.test.filters.LargeTest;
 import androidx.test.rule.ActivityTestRule;
@@ -58,7 +58,8 @@
     }
 
     @Rule
-    public ActivityTestRule<StubActivity> mActivityRule = new ActivityTestRule(StubActivity.class);
+    public ActivityTestRule<PerfTestActivity> mActivityRule =
+            new ActivityTestRule<>(PerfTestActivity.class);
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/VectorDrawablePerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/VectorDrawablePerfTest.java
index 3b2b8a9..d14e93e 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/VectorDrawablePerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/VectorDrawablePerfTest.java
@@ -26,7 +26,7 @@
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.BitmapUtils;
 import android.perftests.utils.PerfStatusReporter;
-import android.perftests.utils.StubActivity;
+import android.perftests.utils.PerfTestActivity;
 import android.test.suitebuilder.annotation.LargeTest;
 
 import androidx.test.rule.ActivityTestRule;
@@ -48,8 +48,8 @@
     private int[] mTestHeights = {512, 1024};
 
     @Rule
-    public ActivityTestRule<StubActivity> mActivityRule =
-            new ActivityTestRule(StubActivity.class);
+    public ActivityTestRule<PerfTestActivity> mActivityRule =
+            new ActivityTestRule<>(PerfTestActivity.class);
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
diff --git a/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java b/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java
index 3aa6749..236f548 100644
--- a/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java
@@ -38,7 +38,8 @@
     private static final String PERMISSION_NAME_DOESNT_EXIST =
             "com.android.perftests.core.TestBadPermission";
     private static final ComponentName TEST_ACTIVITY =
-            new ComponentName("com.android.perftests.core", "android.perftests.utils.StubActivity");
+            new ComponentName("com.android.perftests.core",
+                    "android.perftests.utils.PerfTestActivity");
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
diff --git a/apct-tests/perftests/core/src/android/text/DynamicLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/DynamicLayoutPerfTest.java
index 5be99d9..6b295e5 100644
--- a/apct-tests/perftests/core/src/android/text/DynamicLayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/DynamicLayoutPerfTest.java
@@ -23,7 +23,7 @@
 import android.graphics.Paint.FontMetricsInt;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
-import android.perftests.utils.StubActivity;
+import android.perftests.utils.PerfTestActivity;
 import android.text.style.ReplacementSpan;
 import android.util.ArraySet;
 
@@ -75,7 +75,8 @@
     }
 
     @Rule
-    public ActivityTestRule<StubActivity> mActivityRule = new ActivityTestRule(StubActivity.class);
+    public ActivityTestRule<PerfTestActivity> mActivityRule =
+            new ActivityTestRule<>(PerfTestActivity.class);
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
diff --git a/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java b/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java
index b34001d..b0edb11 100644
--- a/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java
+++ b/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java
@@ -23,7 +23,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
-import android.perftests.utils.StubActivity;
+import android.perftests.utils.PerfTestActivity;
 import android.view.View.MeasureSpec;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
@@ -46,7 +46,8 @@
 public class ViewShowHidePerfTest {
 
     @Rule
-    public ActivityTestRule mActivityRule = new ActivityTestRule(StubActivity.class);
+    public ActivityTestRule<PerfTestActivity> mActivityRule =
+            new ActivityTestRule<>(PerfTestActivity.class);
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
diff --git a/apct-tests/perftests/core/src/android/widget/EditTextBackspacePerfTest.java b/apct-tests/perftests/core/src/android/widget/EditTextBackspacePerfTest.java
index b3ea62a..270b4e5 100644
--- a/apct-tests/perftests/core/src/android/widget/EditTextBackspacePerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/EditTextBackspacePerfTest.java
@@ -18,7 +18,7 @@
 
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
-import android.perftests.utils.StubActivity;
+import android.perftests.utils.PerfTestActivity;
 import android.text.Selection;
 import android.view.KeyEvent;
 import android.view.View.MeasureSpec;
@@ -80,7 +80,8 @@
     }
 
     @Rule
-    public ActivityTestRule<StubActivity> mActivityRule = new ActivityTestRule(StubActivity.class);
+    public ActivityTestRule<PerfTestActivity> mActivityRule =
+            new ActivityTestRule<>(PerfTestActivity.class);
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
diff --git a/apct-tests/perftests/core/src/android/widget/EditTextCursorMovementPerfTest.java b/apct-tests/perftests/core/src/android/widget/EditTextCursorMovementPerfTest.java
index aa47d5b..8028f11 100644
--- a/apct-tests/perftests/core/src/android/widget/EditTextCursorMovementPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/EditTextCursorMovementPerfTest.java
@@ -18,7 +18,7 @@
 
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
-import android.perftests.utils.StubActivity;
+import android.perftests.utils.PerfTestActivity;
 import android.text.Selection;
 import android.view.KeyEvent;
 import android.view.View.MeasureSpec;
@@ -74,7 +74,8 @@
     }
 
     @Rule
-    public ActivityTestRule<StubActivity> mActivityRule = new ActivityTestRule(StubActivity.class);
+    public ActivityTestRule<PerfTestActivity> mActivityRule =
+            new ActivityTestRule<>(PerfTestActivity.class);
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
diff --git a/apct-tests/perftests/core/src/android/widget/EditTextLongTextPerfTest.java b/apct-tests/perftests/core/src/android/widget/EditTextLongTextPerfTest.java
index e50016c..f4ad5dd 100644
--- a/apct-tests/perftests/core/src/android/widget/EditTextLongTextPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/EditTextLongTextPerfTest.java
@@ -19,7 +19,7 @@
 import android.app.Activity;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
-import android.perftests.utils.StubActivity;
+import android.perftests.utils.PerfTestActivity;
 import android.view.KeyEvent;
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
@@ -59,7 +59,8 @@
     }
 
     @Rule
-    public ActivityTestRule<StubActivity> mActivityRule = new ActivityTestRule(StubActivity.class);
+    public ActivityTestRule<PerfTestActivity> mActivityRule =
+            new ActivityTestRule<>(PerfTestActivity.class);
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
diff --git a/apct-tests/perftests/core/src/android/widget/LayoutPerfTest.java b/apct-tests/perftests/core/src/android/widget/LayoutPerfTest.java
index 644095b..223a316 100644
--- a/apct-tests/perftests/core/src/android/widget/LayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/LayoutPerfTest.java
@@ -28,7 +28,7 @@
 import android.os.Looper;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
-import android.perftests.utils.StubActivity;
+import android.perftests.utils.PerfTestActivity;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -72,8 +72,8 @@
     }
 
     @Rule
-    public ActivityTestRule<StubActivity> mActivityRule =
-            new ActivityTestRule(StubActivity.class);
+    public ActivityTestRule<PerfTestActivity> mActivityRule =
+            new ActivityTestRule(PerfTestActivity.class);
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
diff --git a/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java
index bed173b..694e1f4 100644
--- a/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java
@@ -22,7 +22,7 @@
 import android.os.Looper;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
-import android.perftests.utils.StubActivity;
+import android.perftests.utils.PerfTestActivity;
 
 import androidx.test.filters.LargeTest;
 import androidx.test.rule.ActivityTestRule;
@@ -64,8 +64,8 @@
     }
 
     @Rule
-    public ActivityTestRule<StubActivity> mActivityRule =
-            new ActivityTestRule(StubActivity.class);
+    public ActivityTestRule<PerfTestActivity> mActivityRule =
+            new ActivityTestRule(PerfTestActivity.class);
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
diff --git a/apct-tests/perftests/core/src/android/widget/TextViewSetTextLocalePerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewSetTextLocalePerfTest.java
index 00bd8db..a546667 100644
--- a/apct-tests/perftests/core/src/android/widget/TextViewSetTextLocalePerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/TextViewSetTextLocalePerfTest.java
@@ -18,7 +18,7 @@
 
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
-import android.perftests.utils.StubActivity;
+import android.perftests.utils.PerfTestActivity;
 
 import androidx.test.filters.LargeTest;
 import androidx.test.rule.ActivityTestRule;
@@ -56,7 +56,8 @@
     }
 
     @Rule
-    public ActivityTestRule<StubActivity> mActivityRule = new ActivityTestRule(StubActivity.class);
+    public ActivityTestRule<PerfTestActivity> mActivityRule =
+            new ActivityTestRule<>(PerfTestActivity.class);
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
diff --git a/apct-tests/perftests/core/src/android/wm/InternalWindowOperationPerfTest.java b/apct-tests/perftests/core/src/android/wm/InternalWindowOperationPerfTest.java
new file mode 100644
index 0000000..c096cd2
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/wm/InternalWindowOperationPerfTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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 android.wm;
+
+import static android.perftests.utils.ManualBenchmarkState.StatsReport;
+
+import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
+import android.perftests.utils.ManualBenchmarkState;
+import android.perftests.utils.ManualBenchmarkState.ManualBenchmarkTest;
+import android.perftests.utils.PerfManualStatusReporter;
+import android.perftests.utils.TraceMarkParser;
+import android.perftests.utils.TraceMarkParser.TraceMarkSlice;
+import android.util.Log;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.lifecycle.Stage;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.concurrent.TimeUnit;
+
+/** Measure the performance of internal methods in window manager service by trace tag. */
+@LargeTest
+public class InternalWindowOperationPerfTest extends WindowManagerPerfTestBase {
+    private static final String TAG = InternalWindowOperationPerfTest.class.getSimpleName();
+
+    @Rule
+    public final PerfManualStatusReporter mPerfStatusReporter = new PerfManualStatusReporter();
+
+    @Rule
+    public final PerfTestActivityRule mActivityRule = new PerfTestActivityRule();
+
+    private final TraceMarkParser mTraceMarkParser = new TraceMarkParser(
+            "applyPostLayoutPolicy",
+            "applySurfaceChanges",
+            "AppTransitionReady",
+            "closeSurfaceTransactiom",
+            "openSurfaceTransaction",
+            "performLayout",
+            "performSurfacePlacement",
+            "prepareSurfaces",
+            "updateInputWindows",
+            "WSA#startAnimation",
+            "activityIdle",
+            "activityPaused",
+            "activityStopped",
+            "activityDestroyed",
+            "finishActivity",
+            "startActivityInner");
+
+    @Test
+    @ManualBenchmarkTest(
+            targetTestDurationNs = 20 * TIME_1_S_IN_NS,
+            statsReport = @StatsReport(
+                    flags = StatsReport.FLAG_ITERATION | StatsReport.FLAG_MEAN
+                            | StatsReport.FLAG_MAX | StatsReport.FLAG_COEFFICIENT_VAR))
+    public void testLaunchAndFinishActivity() throws Throwable {
+        final ManualBenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        long measuredTimeNs = 0;
+        boolean isTraceStarted = false;
+
+        while (state.keepRunning(measuredTimeNs)) {
+            if (!isTraceStarted && !state.isWarmingUp()) {
+                startAsyncAtrace();
+                isTraceStarted = true;
+            }
+            final long startTime = SystemClock.elapsedRealtimeNanos();
+            mActivityRule.launchActivity();
+            mActivityRule.finishActivity();
+            mActivityRule.waitForIdleSync(Stage.DESTROYED);
+            measuredTimeNs = SystemClock.elapsedRealtimeNanos() - startTime;
+        }
+
+        stopAsyncAtrace();
+
+        mTraceMarkParser.forAllSlices((key, slices) -> {
+            for (TraceMarkSlice slice : slices) {
+                state.addExtraResult(key, (long) (slice.getDurarionInSeconds() * NANOS_PER_S));
+            }
+        });
+
+        Log.i(TAG, String.valueOf(mTraceMarkParser));
+    }
+
+    private void startAsyncAtrace() throws IOException {
+        sUiAutomation.executeShellCommand("atrace -b 32768 --async_start wm");
+        // Avoid atrace isn't ready immediately.
+        SystemClock.sleep(TimeUnit.NANOSECONDS.toMillis(TIME_1_S_IN_NS));
+    }
+
+    private void stopAsyncAtrace() throws IOException {
+        final ParcelFileDescriptor pfd = sUiAutomation.executeShellCommand("atrace --async_stop");
+        final InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                mTraceMarkParser.visit(line);
+            }
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/wm/RecentsAnimationPerfTest.java b/apct-tests/perftests/core/src/android/wm/RecentsAnimationPerfTest.java
index 9cfc3d2..73b4a19 100644
--- a/apct-tests/perftests/core/src/android/wm/RecentsAnimationPerfTest.java
+++ b/apct-tests/perftests/core/src/android/wm/RecentsAnimationPerfTest.java
@@ -16,16 +16,13 @@
 
 package android.wm;
 
-import static android.perftests.utils.ManualBenchmarkState.STATS_REPORT_COEFFICIENT_VAR;
-import static android.perftests.utils.ManualBenchmarkState.STATS_REPORT_ITERATION;
-import static android.perftests.utils.ManualBenchmarkState.STATS_REPORT_MEAN;
+import static android.perftests.utils.ManualBenchmarkState.StatsReport;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.hamcrest.core.AnyOf.anyOf;
 import static org.hamcrest.core.Is.is;
 
-import android.app.Activity;
 import android.app.ActivityManager.TaskSnapshot;
 import android.app.ActivityTaskManager;
 import android.app.IActivityTaskManager;
@@ -39,23 +36,16 @@
 import android.perftests.utils.ManualBenchmarkState;
 import android.perftests.utils.ManualBenchmarkState.ManualBenchmarkTest;
 import android.perftests.utils.PerfManualStatusReporter;
-import android.perftests.utils.StubActivity;
 import android.util.Pair;
 import android.view.IRecentsAnimationController;
 import android.view.IRecentsAnimationRunner;
 import android.view.RemoteAnimationTarget;
-import android.view.WindowManager;
 
 import androidx.test.filters.LargeTest;
-import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.lifecycle.ActivityLifecycleCallback;
-import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
 import androidx.test.runner.lifecycle.Stage;
 
-import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Assume;
-import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
@@ -77,11 +67,10 @@
     public final PerfManualStatusReporter mPerfStatusReporter = new PerfManualStatusReporter();
 
     @Rule
-    public final ActivityTestRule<StubActivity> mActivityRule = new ActivityTestRule<>(
-            StubActivity.class, false /* initialTouchMode */, false /* launchActivity */);
+    public final PerfTestActivityRule mActivityRule =
+            new PerfTestActivityRule(true /* launchActivity */);
 
     private long mMeasuredTimeNs;
-    private LifecycleListener mLifecycleListener;
 
     @Parameterized.Parameter(0)
     public int intervalBetweenOperations;
@@ -127,24 +116,6 @@
         sUiAutomation.dropShellPermissionIdentity();
     }
 
-    @Before
-    @Override
-    public void setUp() {
-        super.setUp();
-        final Activity testActivity = mActivityRule.launchActivity(null /* intent */);
-        try {
-            mActivityRule.runOnUiThread(() -> testActivity.getWindow()
-                    .addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON));
-        } catch (Throwable ignored) { }
-        mLifecycleListener = new LifecycleListener(testActivity);
-        ActivityLifecycleMonitorRegistry.getInstance().addLifecycleCallback(mLifecycleListener);
-    }
-
-    @After
-    public void tearDown() {
-        ActivityLifecycleMonitorRegistry.getInstance().removeLifecycleCallback(mLifecycleListener);
-    }
-
     /** Simulate the timing of touch. */
     private void makeInterval() {
         SystemClock.sleep(intervalBetweenOperations);
@@ -167,8 +138,8 @@
     @ManualBenchmarkTest(
             warmupDurationNs = TIME_1_S_IN_NS,
             targetTestDurationNs = TIME_5_S_IN_NS,
-            statsReportFlags =
-                    STATS_REPORT_ITERATION | STATS_REPORT_MEAN | STATS_REPORT_COEFFICIENT_VAR)
+            statsReport = @StatsReport(flags = StatsReport.FLAG_ITERATION | StatsReport.FLAG_MEAN
+                    | StatsReport.FLAG_COEFFICIENT_VAR))
     public void testRecentsAnimation() throws Throwable {
         final ManualBenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         final IActivityTaskManager atm = ActivityTaskManager.getService();
@@ -201,7 +172,7 @@
                 state.addExtraResult(finishCase.first, elapsedTimeNsOfFinish);
 
                 if (moveRecentsToTop) {
-                    mLifecycleListener.waitForIdleSync(Stage.STOPPED);
+                    mActivityRule.waitForIdleSync(Stage.STOPPED);
 
                     startTime = SystemClock.elapsedRealtimeNanos();
                     atm.startActivityFromRecents(testActivityTaskId, null /* options */);
@@ -209,7 +180,7 @@
                     mMeasuredTimeNs += elapsedTimeNs;
                     state.addExtraResult("startFromRecents", elapsedTimeNs);
 
-                    mLifecycleListener.waitForIdleSync(Stage.RESUMED);
+                    mActivityRule.waitForIdleSync(Stage.RESUMED);
                 }
 
                 makeInterval();
@@ -223,55 +194,18 @@
             }
         };
 
+        recentsSemaphore.tryAcquire();
         while (state.keepRunning(mMeasuredTimeNs)) {
-            Assume.assumeTrue(recentsSemaphore.tryAcquire(TIME_5_S_IN_NS, TimeUnit.NANOSECONDS));
+            mMeasuredTimeNs = 0;
 
             final long startTime = SystemClock.elapsedRealtimeNanos();
             atm.startRecentsActivity(sRecentsIntent, null /* unused */, anim);
             final long elapsedTimeNsOfStart = SystemClock.elapsedRealtimeNanos() - startTime;
             mMeasuredTimeNs += elapsedTimeNsOfStart;
             state.addExtraResult("start", elapsedTimeNsOfStart);
-        }
 
-        // Ensure the last round of animation callback is done.
-        recentsSemaphore.tryAcquire(TIME_5_S_IN_NS, TimeUnit.NANOSECONDS);
-        recentsSemaphore.release();
-    }
-
-    private static class LifecycleListener implements ActivityLifecycleCallback {
-        private final Activity mTargetActivity;
-        private Stage mWaitingStage;
-        private Stage mReceivedStage;
-
-        LifecycleListener(Activity activity) {
-            mTargetActivity = activity;
-        }
-
-        void waitForIdleSync(Stage state) {
-            synchronized (this) {
-                if (state != mReceivedStage) {
-                    mWaitingStage = state;
-                    try {
-                        wait(TimeUnit.NANOSECONDS.toMillis(TIME_5_S_IN_NS));
-                    } catch (InterruptedException impossible) { }
-                }
-                mWaitingStage = mReceivedStage = null;
-            }
-            getInstrumentation().waitForIdleSync();
-        }
-
-        @Override
-        public void onActivityLifecycleChanged(Activity activity, Stage stage) {
-            if (mTargetActivity != activity) {
-                return;
-            }
-
-            synchronized (this) {
-                mReceivedStage = stage;
-                if (mWaitingStage == mReceivedStage) {
-                    notifyAll();
-                }
-            }
+            // Ensure the animation callback is done.
+            Assume.assumeTrue(recentsSemaphore.tryAcquire(TIME_5_S_IN_NS, TimeUnit.NANOSECONDS));
         }
     }
 }
diff --git a/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
index f0c474b..f43bdf8 100644
--- a/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
@@ -24,7 +24,7 @@
 import android.os.RemoteException;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
-import android.perftests.utils.StubActivity;
+import android.perftests.utils.PerfTestActivity;
 import android.util.MergedConfiguration;
 import android.view.DisplayCutout;
 import android.view.IWindow;
@@ -57,8 +57,8 @@
     public final PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
 
     @Rule
-    public final ActivityTestRule<StubActivity> mActivityRule =
-            new ActivityTestRule<>(StubActivity.class);
+    public final ActivityTestRule<PerfTestActivity> mActivityRule =
+            new ActivityTestRule<>(PerfTestActivity.class);
 
     /** This is only a placement to match the input parameters from {@link #getParameters}. */
     @Parameterized.Parameter(0)
diff --git a/apct-tests/perftests/core/src/android/wm/WindowManagerPerfTestBase.java b/apct-tests/perftests/core/src/android/wm/WindowManagerPerfTestBase.java
index 4864da4..4d278c3 100644
--- a/apct-tests/perftests/core/src/android/wm/WindowManagerPerfTestBase.java
+++ b/apct-tests/perftests/core/src/android/wm/WindowManagerPerfTestBase.java
@@ -18,9 +18,21 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
+import android.app.Activity;
 import android.app.UiAutomation;
+import android.content.Intent;
+import android.perftests.utils.PerfTestActivity;
 
-import org.junit.Before;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.lifecycle.ActivityLifecycleCallback;
+import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
+import androidx.test.runner.lifecycle.Stage;
+
+import org.junit.BeforeClass;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import java.util.concurrent.TimeUnit;
 
 public class WindowManagerPerfTestBase {
     static final UiAutomation sUiAutomation = getInstrumentation().getUiAutomation();
@@ -28,10 +40,102 @@
     static final long TIME_1_S_IN_NS = 1 * NANOS_PER_S;
     static final long TIME_5_S_IN_NS = 5 * NANOS_PER_S;
 
-    @Before
-    public void setUp() {
+    @BeforeClass
+    public static void setUpOnce() {
         // In order to be closer to the real use case.
         sUiAutomation.executeShellCommand("input keyevent KEYCODE_WAKEUP");
         sUiAutomation.executeShellCommand("wm dismiss-keyguard");
+        getInstrumentation().getContext().startActivity(new Intent(Intent.ACTION_MAIN)
+                .addCategory(Intent.CATEGORY_HOME).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+    }
+
+    /**
+     * Provides an activity that keeps screen on and is able to wait for a stable lifecycle stage.
+     */
+    static class PerfTestActivityRule extends ActivityTestRule<PerfTestActivity> {
+        private final Intent mStartIntent =
+                new Intent().putExtra(PerfTestActivity.INTENT_EXTRA_KEEP_SCREEN_ON, true);
+        private final LifecycleListener mLifecycleListener = new LifecycleListener();
+
+        PerfTestActivityRule() {
+            this(false /* launchActivity */);
+        }
+
+        PerfTestActivityRule(boolean launchActivity) {
+            super(PerfTestActivity.class, false /* initialTouchMode */, launchActivity);
+        }
+
+        @Override
+        public Statement apply(Statement base, Description description) {
+            final Statement wrappedStatement = new Statement() {
+                @Override
+                public void evaluate() throws Throwable {
+                    ActivityLifecycleMonitorRegistry.getInstance()
+                            .addLifecycleCallback(mLifecycleListener);
+                    base.evaluate();
+                    ActivityLifecycleMonitorRegistry.getInstance()
+                            .removeLifecycleCallback(mLifecycleListener);
+                }
+            };
+            return super.apply(wrappedStatement, description);
+        }
+
+        @Override
+        protected Intent getActivityIntent() {
+            return mStartIntent;
+        }
+
+        @Override
+        public PerfTestActivity launchActivity(Intent intent) {
+            final PerfTestActivity activity = super.launchActivity(intent);
+            mLifecycleListener.setTargetActivity(activity);
+            return activity;
+        }
+
+        PerfTestActivity launchActivity() {
+            return launchActivity(mStartIntent);
+        }
+
+        void waitForIdleSync(Stage state) {
+            mLifecycleListener.waitForIdleSync(state);
+        }
+    }
+
+    static class LifecycleListener implements ActivityLifecycleCallback {
+        private Activity mTargetActivity;
+        private Stage mWaitingStage;
+        private Stage mReceivedStage;
+
+        void setTargetActivity(Activity activity) {
+            mTargetActivity = activity;
+            mReceivedStage = mWaitingStage = null;
+        }
+
+        void waitForIdleSync(Stage stage) {
+            synchronized (this) {
+                if (stage != mReceivedStage) {
+                    mWaitingStage = stage;
+                    try {
+                        wait(TimeUnit.NANOSECONDS.toMillis(TIME_5_S_IN_NS));
+                    } catch (InterruptedException impossible) { }
+                }
+                mWaitingStage = mReceivedStage = null;
+            }
+            getInstrumentation().waitForIdleSync();
+        }
+
+        @Override
+        public void onActivityLifecycleChanged(Activity activity, Stage stage) {
+            if (mTargetActivity != activity) {
+                return;
+            }
+
+            synchronized (this) {
+                mReceivedStage = stage;
+                if (mWaitingStage == mReceivedStage) {
+                    notifyAll();
+                }
+            }
+        }
     }
 }
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java b/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java
index ffe39e8..a83254b 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java
@@ -59,27 +59,37 @@
 public final class ManualBenchmarkState {
     private static final String TAG = ManualBenchmarkState.class.getSimpleName();
 
-    @IntDef(prefix = {"STATS_REPORT"}, value = {
-            STATS_REPORT_MEDIAN,
-            STATS_REPORT_MEAN,
-            STATS_REPORT_MIN,
-            STATS_REPORT_MAX,
-            STATS_REPORT_PERCENTILE90,
-            STATS_REPORT_PERCENTILE95,
-            STATS_REPORT_STDDEV,
-            STATS_REPORT_ITERATION,
-    })
-    public @interface StatsReport {}
+    @Target(ElementType.ANNOTATION_TYPE)
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface StatsReport {
+        int FLAG_MEDIAN = 0x00000001;
+        int FLAG_MEAN = 0x00000002;
+        int FLAG_MIN = 0x00000004;
+        int FLAG_MAX = 0x00000008;
+        int FLAG_STDDEV = 0x00000010;
+        int FLAG_COEFFICIENT_VAR = 0x00000020;
+        int FLAG_ITERATION = 0x00000040;
 
-    public static final int STATS_REPORT_MEDIAN = 0x00000001;
-    public static final int STATS_REPORT_MEAN = 0x00000002;
-    public static final int STATS_REPORT_MIN = 0x00000004;
-    public static final int STATS_REPORT_MAX = 0x00000008;
-    public static final int STATS_REPORT_PERCENTILE90 = 0x00000010;
-    public static final int STATS_REPORT_PERCENTILE95 = 0x00000020;
-    public static final int STATS_REPORT_STDDEV = 0x00000040;
-    public static final int STATS_REPORT_COEFFICIENT_VAR = 0x00000080;
-    public static final int STATS_REPORT_ITERATION = 0x00000100;
+        @Retention(RetentionPolicy.RUNTIME)
+        @IntDef(value = {
+                FLAG_MEDIAN,
+                FLAG_MEAN,
+                FLAG_MIN,
+                FLAG_MAX,
+                FLAG_STDDEV,
+                FLAG_COEFFICIENT_VAR,
+                FLAG_ITERATION,
+        })
+        @interface Flag {}
+
+        /** Defines which type of statistics should output. */
+        @Flag int flags() default -1;
+        /** An array with value 0~100 to provide the percentiles. */
+        int[] percentiles() default {};
+    }
+
+    /** It means the entire {@link StatsReport} is not given. */
+    private static final int DEFAULT_STATS_REPORT = -2;
 
     // TODO: Tune these values.
     // warm-up for duration
@@ -116,8 +126,9 @@
     // The computation needs double precision, but long int is fine for final reporting.
     private Stats mStats;
 
-    private int mStatsReportFlags = STATS_REPORT_MEDIAN | STATS_REPORT_MEAN
-            | STATS_REPORT_PERCENTILE90 | STATS_REPORT_PERCENTILE95 | STATS_REPORT_STDDEV;
+    private int mStatsReportFlags =
+            StatsReport.FLAG_MEDIAN | StatsReport.FLAG_MEAN | StatsReport.FLAG_STDDEV;
+    private int[] mStatsReportPercentiles = {90 , 95};
 
     private boolean shouldReport(int statsReportFlag) {
         return (mStatsReportFlags & statsReportFlag) != 0;
@@ -136,9 +147,10 @@
         if (targetTestDurationNs >= 0) {
             mTargetTestDurationNs = targetTestDurationNs;
         }
-        final int statsReportFlags = testAnnotation.statsReportFlags();
-        if (statsReportFlags >= 0) {
-            mStatsReportFlags = statsReportFlags;
+        final StatsReport statsReport = testAnnotation.statsReport();
+        if (statsReport != null && statsReport.flags() != DEFAULT_STATS_REPORT) {
+            mStatsReportFlags = statsReport.flags();
+            mStatsReportPercentiles = statsReport.percentiles();
         }
     }
 
@@ -189,11 +201,20 @@
     }
 
     /**
-     * Adds additional result while this benchmark is running. It is used when a sequence of
+     * @return {@code true} if the benchmark is in warmup state. It can be used to skip the
+     *         operations or measurements that are unnecessary while the test isn't running the
+     *         actual benchmark.
+     */
+    public boolean isWarmingUp() {
+        return mState == WARMUP;
+    }
+
+    /**
+     * Adds additional result while this benchmark isn't warming up. It is used when a sequence of
      * operations is executed consecutively, the duration of each operation can also be recorded.
      */
     public void addExtraResult(String key, long duration) {
-        if (mState != RUNNING) {
+        if (isWarmingUp()) {
             return;
         }
         if (mExtraResults == null) {
@@ -221,31 +242,30 @@
     }
 
     private void fillStatus(Bundle status, String key, Stats stats) {
-        if (shouldReport(STATS_REPORT_ITERATION)) {
+        if (shouldReport(StatsReport.FLAG_ITERATION)) {
             status.putLong(key + "_iteration", stats.getSize());
         }
-        if (shouldReport(STATS_REPORT_MEDIAN)) {
+        if (shouldReport(StatsReport.FLAG_MEDIAN)) {
             status.putLong(key + "_median", stats.getMedian());
         }
-        if (shouldReport(STATS_REPORT_MEAN)) {
+        if (shouldReport(StatsReport.FLAG_MEAN)) {
             status.putLong(key + "_mean", Math.round(stats.getMean()));
         }
-        if (shouldReport(STATS_REPORT_MIN)) {
+        if (shouldReport(StatsReport.FLAG_MIN)) {
             status.putLong(key + "_min", stats.getMin());
         }
-        if (shouldReport(STATS_REPORT_MAX)) {
+        if (shouldReport(StatsReport.FLAG_MAX)) {
             status.putLong(key + "_max", stats.getMax());
         }
-        if (shouldReport(STATS_REPORT_PERCENTILE90)) {
-            status.putLong(key + "_percentile90", stats.getPercentile90());
+        if (mStatsReportPercentiles != null) {
+            for (int percentile : mStatsReportPercentiles) {
+                status.putLong(key + "_percentile" + percentile, stats.getPercentile(percentile));
+            }
         }
-        if (shouldReport(STATS_REPORT_PERCENTILE95)) {
-            status.putLong(key + "_percentile95", stats.getPercentile95());
-        }
-        if (shouldReport(STATS_REPORT_STDDEV)) {
+        if (shouldReport(StatsReport.FLAG_STDDEV)) {
             status.putLong(key + "_stddev", Math.round(stats.getStandardDeviation()));
         }
-        if (shouldReport(STATS_REPORT_COEFFICIENT_VAR)) {
+        if (shouldReport(StatsReport.FLAG_COEFFICIENT_VAR)) {
             status.putLong(key + "_cv",
                     Math.round((100 * stats.getStandardDeviation() / stats.getMean())));
         }
@@ -276,6 +296,6 @@
     public @interface ManualBenchmarkTest {
         long warmupDurationNs() default -1;
         long targetTestDurationNs() default -1;
-        @StatsReport int statsReportFlags() default -1;
+        StatsReport statsReport() default @StatsReport(flags = DEFAULT_STATS_REPORT);
     }
 }
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/PerfTestActivity.java b/apct-tests/perftests/utils/src/android/perftests/utils/PerfTestActivity.java
new file mode 100644
index 0000000..e934feb
--- /dev/null
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/PerfTestActivity.java
@@ -0,0 +1,46 @@
+/*
+ * 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 android.perftests.utils;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+/**
+ * A simple activity used for testing, e.g. performance of activity switching, or as a base
+ * container of testing view.
+ */
+public class PerfTestActivity extends Activity {
+    public static final String INTENT_EXTRA_KEEP_SCREEN_ON = "keep_screen_on";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (getIntent().getBooleanExtra(INTENT_EXTRA_KEEP_SCREEN_ON, false)) {
+            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        }
+    }
+
+    public static Intent createLaunchIntent(Context context) {
+        final Intent intent = new Intent();
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.setClass(context, PerfTestActivity.class);
+        return intent;
+    }
+}
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/Stats.java b/apct-tests/perftests/utils/src/android/perftests/utils/Stats.java
index f650e81..fb516a8 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/Stats.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/Stats.java
@@ -16,34 +16,34 @@
 
 package android.perftests.utils;
 
+import android.annotation.IntRange;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 public class Stats {
-    private long mMedian, mMin, mMax, mPercentile90, mPercentile95;
+    private long mMedian, mMin, mMax;
     private double mMean, mStandardDeviation;
-    private final int mSize;
+    private final List<Long> mValues;
 
     /* Calculate stats in constructor. */
     public Stats(List<Long> values) {
-        // make a copy since we're modifying it
-        values = new ArrayList<>(values);
         final int size = values.size();
         if (size < 2) {
             throw new IllegalArgumentException("At least two results are necessary.");
         }
 
+        // Make a copy since we're modifying it.
+        mValues = values = new ArrayList<>(values);
+
         Collections.sort(values);
 
-        mSize = size;
         mMin = values.get(0);
         mMax = values.get(values.size() - 1);
 
         mMedian = size % 2 == 0 ? (values.get(size / 2) + values.get(size / 2 - 1)) / 2 :
                 values.get(size / 2);
-        mPercentile90 = getPercentile(values, 90);
-        mPercentile95 = getPercentile(values, 95);
 
         for (int i = 0; i < size; ++i) {
             long result = values.get(i);
@@ -59,7 +59,7 @@
     }
 
     public int getSize() {
-        return mSize;
+        return mValues.size();
     }
 
     public double getMean() {
@@ -82,12 +82,8 @@
         return mStandardDeviation;
     }
 
-    public long getPercentile90() {
-        return mPercentile90;
-    }
-
-    public long getPercentile95() {
-        return mPercentile95;
+    public long getPercentile(@IntRange(from = 0, to = 100) int percentile) {
+        return getPercentile(mValues, percentile);
     }
 
     private static long getPercentile(List<Long> values, int percentile) {
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/StubActivity.java b/apct-tests/perftests/utils/src/android/perftests/utils/StubActivity.java
deleted file mode 100644
index 8f03f7e..0000000
--- a/apct-tests/perftests/utils/src/android/perftests/utils/StubActivity.java
+++ /dev/null
@@ -1,30 +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 android.perftests.utils;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-
-public class StubActivity extends Activity {
-    public static Intent createLaunchIntent(Context context) {
-        final Intent intent = new Intent();
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.setClass(context, StubActivity.class);
-        return intent;
-    }
-}
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/TraceMarkParser.java b/apct-tests/perftests/utils/src/android/perftests/utils/TraceMarkParser.java
new file mode 100644
index 0000000..1afed3a
--- /dev/null
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/TraceMarkParser.java
@@ -0,0 +1,232 @@
+/*
+ * 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 android.perftests.utils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.Predicate;
+
+/**
+ * Utility to get the slice of tracing_mark_write S,F,B,E (Async: start, finish, Sync: begin, end).
+ * Use {@link #visit(String)} to process the trace in text form. The filtered results can be
+ * obtained by {@link #forAllSlices(BiConsumer)}.
+ *
+ * @see android.os.Trace
+ */
+public class TraceMarkParser {
+    /** All slices by the name of {@link TraceMarkLine}. */
+    private final Map<String, List<TraceMarkSlice>> mSlicesMap = new HashMap<>();
+    /** The nested depth of each task-pid. */
+    private final Map<String, Integer> mDepthMap = new HashMap<>();
+    /** The start trace lines that haven't matched the corresponding end. */
+    private final Map<String, TraceMarkLine> mPendingStarts = new HashMap<>();
+
+    private final Predicate<TraceMarkLine> mTraceLineFilter;
+
+    public TraceMarkParser(Predicate<TraceMarkLine> traceLineFilter) {
+        mTraceLineFilter = traceLineFilter;
+    }
+
+    /** Only accept the trace event with the given names. */
+    public TraceMarkParser(String... traceNames) {
+        this(line -> {
+            for (String name : traceNames) {
+                if (name.equals(line.name)) {
+                    return true;
+                }
+            }
+            return false;
+        });
+    }
+
+    /** Computes {@link TraceMarkSlice} by the given trace line. */
+    public void visit(String textTraceLine) {
+        final TraceMarkLine line = TraceMarkLine.parse(textTraceLine);
+        if (line == null) {
+            return;
+        }
+
+        if (line.isAsync) {
+            // Async-trace contains name in the start and finish event.
+            if (mTraceLineFilter.test(line)) {
+                if (line.isBegin) {
+                    mPendingStarts.put(line.name, line);
+                } else {
+                    final TraceMarkLine start = mPendingStarts.remove(line.name);
+                    if (start != null) {
+                        addSlice(start, line);
+                    }
+                }
+            }
+            return;
+        }
+
+        int depth = 1;
+        if (line.isBegin) {
+            final Integer existingDepth = mDepthMap.putIfAbsent(line.taskPid, 1);
+            if (existingDepth != null) {
+                mDepthMap.put(line.taskPid, depth = existingDepth + 1);
+            }
+            // Sync-trace only contains name in the begin event.
+            if (mTraceLineFilter.test(line)) {
+                mPendingStarts.put(getSyncPendingStartKey(line, depth), line);
+            }
+        } else {
+            final Integer existingDepth = mDepthMap.get(line.taskPid);
+            if (existingDepth != null) {
+                depth = existingDepth;
+                mDepthMap.put(line.taskPid, existingDepth - 1);
+            }
+            final TraceMarkLine begin = mPendingStarts.remove(getSyncPendingStartKey(line, depth));
+            if (begin != null) {
+                addSlice(begin, line);
+            }
+        }
+    }
+
+    private static String getSyncPendingStartKey(TraceMarkLine line, int depth) {
+        return line.taskPid + "@" + depth;
+    }
+
+    private void addSlice(TraceMarkLine begin, TraceMarkLine end) {
+        mSlicesMap.computeIfAbsent(
+                begin.name, k -> new ArrayList<>()).add(new TraceMarkSlice(begin, end));
+    }
+
+    public void forAllSlices(BiConsumer<String, List<TraceMarkSlice>> consumer) {
+        for (Map.Entry<String, List<TraceMarkSlice>> entry : mSlicesMap.entrySet()) {
+            consumer.accept(entry.getKey(), entry.getValue());
+        }
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        forAllSlices((key, slices) -> {
+            double totalMs = 0;
+            for (TraceMarkSlice s : slices) {
+                totalMs += s.getDurarionInSeconds() * 1000;
+            }
+            sb.append(key).append(" count=").append(slices.size()).append(" avg=")
+                    .append(totalMs / slices.size()).append("ms\n");
+        });
+
+        if (!mPendingStarts.isEmpty()) {
+            sb.append("[Warning] Unresolved events:").append(mPendingStarts).append("\n");
+        }
+        return sb.toString();
+    }
+
+    public static class TraceMarkSlice {
+        public final TraceMarkLine begin;
+        public final TraceMarkLine end;
+
+        TraceMarkSlice(TraceMarkLine begin, TraceMarkLine end) {
+            this.begin = begin;
+            this.end = end;
+        }
+
+        public double getDurarionInSeconds() {
+            return end.timestamp - begin.timestamp;
+        }
+    }
+
+    // taskPid                               timestamp                           name
+    // # Async:
+    // Binder:129_F-349  ( 1296) [003] ...1  12.2776: tracing_mark_write: S|1296|launching: a.test|0
+    // android.anim-135  ( 1296) [005] ...1  12.3361: tracing_mark_write: F|1296|launching: a.test|0
+    // # Normal:
+    // Binder:129_6-315  ( 1296) [007] ...1  97.4576: tracing_mark_write: B|1296|relayoutWindow: xxx
+    // ... there may have other nested begin/end
+    // Binder:129_6-315  ( 1296) [007] ...1  97.4580: tracing_mark_write: E|1296
+    public static class TraceMarkLine {
+        static final String EVENT_KEYWORD = ": tracing_mark_write: ";
+        static final char ASYNC_START = 'S';
+        static final char ASYNC_FINISH = 'F';
+        static final char SYNC_BEGIN = 'B';
+        static final char SYNC_END = 'E';
+
+        public final String taskPid;
+        public final double timestamp;
+        public final String name;
+        public final boolean isAsync;
+        public final boolean isBegin;
+
+        TraceMarkLine(String rawLine, int typePos, int type) throws IllegalArgumentException {
+            taskPid = rawLine.substring(0, rawLine.indexOf('(')).trim();
+            final int timeEnd = rawLine.indexOf(':', taskPid.length());
+            if (timeEnd < 0) {
+                throw new IllegalArgumentException("Timestamp end not found");
+            }
+            final int timeBegin = rawLine.lastIndexOf(' ', timeEnd);
+            if (timeBegin < 0) {
+                throw new IllegalArgumentException("Timestamp start not found");
+            }
+            timestamp = Double.parseDouble(rawLine.substring(timeBegin, timeEnd));
+            isAsync = type == ASYNC_START || type == ASYNC_FINISH;
+            isBegin = type == ASYNC_START || type == SYNC_BEGIN;
+
+            if (!isAsync && !isBegin) {
+                name = "";
+            } else {
+                // Get the position of the second '|' from "S|1234|name".
+                final int nameBegin = rawLine.indexOf('|', typePos + 2) + 1;
+                if (nameBegin == 0) {
+                    throw new IllegalArgumentException("Name begin not found");
+                }
+                if (isAsync) {
+                    // Get the name from "S|1234|name|0".
+                    name = rawLine.substring(nameBegin, rawLine.lastIndexOf('|'));
+                } else {
+                    name = rawLine.substring(nameBegin);
+                }
+            }
+        }
+
+        static TraceMarkLine parse(String rawLine) {
+            final int eventPos = rawLine.indexOf(EVENT_KEYWORD);
+            if (eventPos < 0) {
+                return null;
+            }
+            final int typePos = eventPos + EVENT_KEYWORD.length();
+            if (typePos >= rawLine.length()) {
+                return null;
+            }
+            final int type = rawLine.charAt(typePos);
+            if (type != ASYNC_START && type != ASYNC_FINISH
+                    && type != SYNC_BEGIN  && type != SYNC_END) {
+                return null;
+            }
+
+            try {
+                return new TraceMarkLine(rawLine, typePos, type);
+            } catch (IllegalArgumentException e) {
+                e.printStackTrace();
+            }
+            return null;
+        }
+
+        @Override
+        public String toString() {
+            return "TraceMarkLine{pid=" + taskPid + " time=" + timestamp + " name=" + name
+                    + " async=" + isAsync + " begin=" + isBegin + "}";
+        }
+    }
+}
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
index 3cfb080..c036c77 100644
--- a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -35,8 +35,6 @@
 
     void onBootPhase(int phase);
 
-    boolean isParoledOrCharging();
-
     void postCheckIdleStates(int userId);
 
     /**
@@ -59,13 +57,15 @@
 
     int getAppId(String packageName);
 
-    boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime,
+    /**
+     * @see #isAppIdleFiltered(String, int, int, long)
+     */
+    boolean isAppIdleFiltered(String packageName, int userId, long elapsedRealtime,
             boolean shouldObfuscateInstantApps);
 
     /**
      * Checks if an app has been idle for a while and filters out apps that are excluded.
      * It returns false if the current system state allows all apps to be considered active.
-     * This happens if the device is plugged in or temporarily allowed to make exceptions.
      * Called by interface impls.
      */
     boolean isAppIdleFiltered(String packageName, int appId, int userId,
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 14d5a68..c3ffad6 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -266,11 +266,6 @@
     boolean mReportedActive;
 
     /**
-     * Are we currently in device-wide standby parole?
-     */
-    volatile boolean mInParole;
-
-    /**
      * A mapping of which uids are currently in the foreground to their effective priority.
      */
     final SparseIntArray mUidPriorityOverride = new SparseIntArray();
@@ -2361,14 +2356,6 @@
         }
 
         @Override
-        public void onParoleStateChanged(boolean isParoleOn) {
-            if (DEBUG_STANDBY) {
-                Slog.i(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
-            }
-            mInParole = isParoleOn;
-        }
-
-        @Override
         public void onUserInteractionStarted(String packageName, int userId) {
             final int uid = mLocalPM.getPackageUid(packageName,
                     PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
@@ -3031,10 +3018,6 @@
             }
             pw.println();
 
-            pw.print("    In parole?: ");
-            pw.print(mInParole);
-            pw.println();
-
             for (int i = mJobRestrictions.size() - 1; i >= 0; i--) {
                 pw.print("    ");
                 mJobRestrictions.get(i).dumpConstants(pw);
@@ -3222,7 +3205,6 @@
             }
             proto.end(settingsToken);
 
-            proto.write(JobSchedulerServiceDumpProto.IN_PAROLE, mInParole);
             for (int i = mJobRestrictions.size() - 1; i >= 0; i--) {
                 mJobRestrictions.get(i).dumpConstants(proto);
             }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 400d902..14dce84 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -414,8 +414,6 @@
     private final Handler mHandler;
     private final QcConstants mQcConstants;
 
-    private volatile boolean mInParole;
-
     /** How much time each app will have to run jobs within their standby bucket window. */
     private long mAllowedTimePerPeriodMs = QcConstants.DEFAULT_ALLOWED_TIME_PER_PERIOD_MS;
 
@@ -711,7 +709,6 @@
     public long getMaxJobExecutionTimeMsLocked(@NonNull final JobStatus jobStatus) {
         // If quota is currently "free", then the job can run for the full amount of time.
         if (mChargeTracker.isCharging()
-                || mInParole
                 || isTopStartedJobLocked(jobStatus)
                 || isUidInForeground(jobStatus.getSourceUid())) {
             return JobServiceContext.EXECUTING_TIMESLICE_MILLIS;
@@ -737,8 +734,8 @@
             final int standbyBucket) {
         if (standbyBucket == NEVER_INDEX) return false;
 
-        // Quota constraint is not enforced while charging or when parole is on.
-        if (mChargeTracker.isCharging() || mInParole) {
+        // Quota constraint is not enforced while charging.
+        if (mChargeTracker.isCharging()) {
             return true;
         }
 
@@ -1780,20 +1777,6 @@
                 }
             });
         }
-
-        @Override
-        public void onParoleStateChanged(final boolean isParoleOn) {
-            mInParole = isParoleOn;
-            if (DEBUG) {
-                Slog.i(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
-            }
-            // Update job bookkeeping out of band.
-            BackgroundThread.getHandler().post(() -> {
-                synchronized (mLock) {
-                    maybeUpdateAllConstraintsLocked();
-                }
-            });
-        }
     }
 
     private final class DeleteTimingSessionsFunctor implements Consumer<List<TimingSession>> {
@@ -2515,7 +2498,6 @@
     public void dumpControllerStateLocked(final IndentingPrintWriter pw,
             final Predicate<JobStatus> predicate) {
         pw.println("Is charging: " + mChargeTracker.isCharging());
-        pw.println("In parole: " + mInParole);
         pw.println("Current elapsed time: " + sElapsedRealtimeClock.millis());
         pw.println();
 
@@ -2639,7 +2621,6 @@
         final long mToken = proto.start(StateControllerProto.QUOTA);
 
         proto.write(StateControllerProto.QuotaController.IS_CHARGING, mChargeTracker.isCharging());
-        proto.write(StateControllerProto.QuotaController.IS_IN_PAROLE, mInParole);
         proto.write(StateControllerProto.QuotaController.ELAPSED_REALTIME,
                 sElapsedRealtimeClock.millis());
 
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 7c472a9..ecc0459 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -45,7 +45,6 @@
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
 
-import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
 import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 
 import android.annotation.UserIdInt;
@@ -70,10 +69,8 @@
 import android.hardware.display.DisplayManager;
 import android.net.ConnectivityManager;
 import android.net.Network;
-import android.net.NetworkInfo;
 import android.net.NetworkRequest;
 import android.net.NetworkScoreManager;
-import android.os.BatteryManager;
 import android.os.BatteryStats;
 import android.os.Environment;
 import android.os.Handler;
@@ -192,21 +189,14 @@
     static final int MSG_INFORM_LISTENERS = 3;
     static final int MSG_FORCE_IDLE_STATE = 4;
     static final int MSG_CHECK_IDLE_STATES = 5;
-    static final int MSG_CHECK_PAROLE_TIMEOUT = 6;
-    static final int MSG_PAROLE_END_TIMEOUT = 7;
     static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8;
-    static final int MSG_PAROLE_STATE_CHANGED = 9;
     static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10;
     /** Check the state of one app: arg1 = userId, arg2 = uid, obj = (String) packageName */
     static final int MSG_CHECK_PACKAGE_IDLE_STATE = 11;
     static final int MSG_REPORT_SYNC_SCHEDULED = 12;
     static final int MSG_REPORT_EXEMPTED_SYNC_START = 13;
-    static final int MSG_UPDATE_STABLE_CHARGING= 14;
 
     long mCheckIdleIntervalMillis;
-    long mAppIdleParoleIntervalMillis;
-    long mAppIdleParoleWindowMillis;
-    long mAppIdleParoleDurationMillis;
     long[] mAppStandbyScreenThresholds = SCREEN_TIME_THRESHOLDS;
     long[] mAppStandbyElapsedThresholds = ELAPSED_TIME_THRESHOLDS;
     /** Minimum time a strong usage event should keep the bucket elevated. */
@@ -244,20 +234,12 @@
      * start is the first usage of the app
      */
     long mInitialForegroundServiceStartTimeoutMillis;
-    /** The length of time phone must be charging before considered stable enough to run jobs  */
-    long mStableChargingThresholdMillis;
 
     private volatile boolean mAppIdleEnabled;
-    boolean mAppIdleTempParoled;
-    boolean mCharging;
-    boolean mChargingStable;
-    private long mLastAppIdleParoledTime;
     private boolean mSystemServicesReady = false;
     // There was a system update, defaults need to be initialized after services are ready
     private boolean mPendingInitializeDefaults;
 
-    private final DeviceStateReceiver mDeviceStateReceiver;
-
     private volatile boolean mPendingOneTimeCheckIdleStates;
 
     private final AppStandbyHandler mHandler;
@@ -267,7 +249,6 @@
 
     private AppWidgetManager mAppWidgetManager;
     private ConnectivityManager mConnectivityManager;
-    private PowerManager mPowerManager;
     private PackageManager mPackageManager;
     Injector mInjector;
 
@@ -329,12 +310,6 @@
         mContext = mInjector.getContext();
         mHandler = new AppStandbyHandler(mInjector.getLooper());
         mPackageManager = mContext.getPackageManager();
-        mDeviceStateReceiver = new DeviceStateReceiver();
-
-        IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING);
-        deviceStates.addAction(BatteryManager.ACTION_DISCHARGING);
-        deviceStates.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
-        mContext.registerReceiver(mDeviceStateReceiver, deviceStates);
 
         synchronized (mAppIdleLock) {
             mAppIdleHistory = new AppIdleHistory(mInjector.getDataSystemDirectory(),
@@ -353,15 +328,7 @@
 
     @VisibleForTesting
     void setAppIdleEnabled(boolean enabled) {
-        synchronized (mAppIdleLock) {
-            if (mAppIdleEnabled != enabled) {
-                final boolean oldParoleState = isParoledOrCharging();
-                mAppIdleEnabled = enabled;
-                if (isParoledOrCharging() != oldParoleState) {
-                    postParoleStateChanged();
-                }
-            }
-        }
+        mAppIdleEnabled = enabled;
     }
 
     @Override
@@ -381,7 +348,6 @@
 
             mAppWidgetManager = mContext.getSystemService(AppWidgetManager.class);
             mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
-            mPowerManager = mContext.getSystemService(PowerManager.class);
 
             mInjector.registerDisplayListener(mDisplayListener, mHandler);
             synchronized (mAppIdleLock) {
@@ -402,8 +368,6 @@
             if (mPendingOneTimeCheckIdleStates) {
                 postOneTimeCheckIdleStates();
             }
-        } else if (phase == PHASE_BOOT_COMPLETED) {
-            setChargingState(mInjector.isCharging());
         }
     }
 
@@ -504,93 +468,6 @@
         }
     }
 
-    @VisibleForTesting
-    void setChargingState(boolean charging) {
-        synchronized (mAppIdleLock) {
-            if (mCharging != charging) {
-                mCharging = charging;
-                if (DEBUG) Slog.d(TAG, "Setting mCharging to " + charging);
-                if (charging) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "Scheduling MSG_UPDATE_STABLE_CHARGING  delay = "
-                                + mStableChargingThresholdMillis);
-                    }
-                    mHandler.sendEmptyMessageDelayed(MSG_UPDATE_STABLE_CHARGING,
-                            mStableChargingThresholdMillis);
-                } else {
-                    mHandler.removeMessages(MSG_UPDATE_STABLE_CHARGING);
-                    updateChargingStableState();
-                }
-            }
-        }
-    }
-
-    private void updateChargingStableState() {
-        synchronized (mAppIdleLock) {
-            if (mChargingStable != mCharging) {
-                if (DEBUG) Slog.d(TAG, "Setting mChargingStable to " + mCharging);
-                mChargingStable = mCharging;
-                postParoleStateChanged();
-            }
-        }
-    }
-
-    private void setAppIdleParoled(boolean paroled) {
-        synchronized (mAppIdleLock) {
-            final long now = mInjector.currentTimeMillis();
-            if (mAppIdleTempParoled != paroled) {
-                mAppIdleTempParoled = paroled;
-                if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleTempParoled);
-                if (paroled) {
-                    postParoleEndTimeout();
-                } else {
-                    mLastAppIdleParoledTime = now;
-                    postNextParoleTimeout(now, false);
-                }
-                postParoleStateChanged();
-            }
-        }
-    }
-
-    @Override
-    public boolean isParoledOrCharging() {
-        if (!mAppIdleEnabled) return true;
-        synchronized (mAppIdleLock) {
-            // Only consider stable charging when determining charge state.
-            return mAppIdleTempParoled || mChargingStable;
-        }
-    }
-
-    private void postNextParoleTimeout(long now, boolean forced) {
-        if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT");
-        mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT);
-        // Compute when the next parole needs to happen. We check more frequently than necessary
-        // since the message handler delays are based on elapsedRealTime and not wallclock time.
-        // The comparison is done in wallclock time.
-        long timeLeft = (mLastAppIdleParoledTime + mAppIdleParoleIntervalMillis) - now;
-        if (forced) {
-            // Set next timeout for the end of the parole window
-            // If parole is not set by the end of the window it will be forced
-            timeLeft += mAppIdleParoleWindowMillis;
-        }
-        if (timeLeft < 0) {
-            timeLeft = 0;
-        }
-        mHandler.sendEmptyMessageDelayed(MSG_CHECK_PAROLE_TIMEOUT, timeLeft);
-    }
-
-    private void postParoleEndTimeout() {
-        if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_END_TIMEOUT");
-        mHandler.removeMessages(MSG_PAROLE_END_TIMEOUT);
-        mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, mAppIdleParoleDurationMillis);
-    }
-
-    private void postParoleStateChanged() {
-        if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_STATE_CHANGED");
-        mHandler.removeMessages(MSG_PAROLE_STATE_CHANGED);
-        mHandler.sendEmptyMessage(MSG_PAROLE_STATE_CHANGED);
-    }
-
     @Override
     public void postCheckIdleStates(int userId) {
         mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
@@ -787,48 +664,6 @@
         return THRESHOLD_BUCKETS[bucketIndex];
     }
 
-    private void checkParoleTimeout() {
-        boolean setParoled = false;
-        boolean waitForNetwork = false;
-        NetworkInfo activeNetwork = mConnectivityManager.getActiveNetworkInfo();
-        boolean networkActive = activeNetwork != null &&
-                activeNetwork.isConnected();
-
-        synchronized (mAppIdleLock) {
-            final long now = mInjector.currentTimeMillis();
-            if (!mAppIdleTempParoled) {
-                final long timeSinceLastParole = now - mLastAppIdleParoledTime;
-                if (timeSinceLastParole > mAppIdleParoleIntervalMillis) {
-                    if (DEBUG) Slog.d(TAG, "Crossed default parole interval");
-                    if (networkActive) {
-                        // If network is active set parole
-                        setParoled = true;
-                    } else {
-                        if (timeSinceLastParole
-                                > mAppIdleParoleIntervalMillis + mAppIdleParoleWindowMillis) {
-                            if (DEBUG) Slog.d(TAG, "Crossed end of parole window, force parole");
-                            setParoled = true;
-                        } else {
-                            if (DEBUG) Slog.d(TAG, "Network unavailable, delaying parole");
-                            waitForNetwork = true;
-                            postNextParoleTimeout(now, true);
-                        }
-                    }
-                } else {
-                    if (DEBUG) Slog.d(TAG, "Not long enough to go to parole");
-                    postNextParoleTimeout(now, false);
-                }
-            }
-        }
-        if (waitForNetwork) {
-            mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
-        }
-        if (setParoled) {
-            // Set parole if network is available
-            setAppIdleParoled(true);
-        }
-    }
-
     private void notifyBatteryStats(String packageName, int userId, boolean idle) {
         try {
             final int uid = mPackageManager.getPackageUidAsUser(packageName,
@@ -844,30 +679,6 @@
         }
     }
 
-    private void onDeviceIdleModeChanged() {
-        final boolean deviceIdle = mPowerManager.isDeviceIdleMode();
-        if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle);
-        boolean paroled = false;
-        synchronized (mAppIdleLock) {
-            final long timeSinceLastParole =
-                    mInjector.currentTimeMillis() - mLastAppIdleParoledTime;
-            if (!deviceIdle
-                    && timeSinceLastParole >= mAppIdleParoleIntervalMillis) {
-                if (DEBUG) {
-                    Slog.i(TAG,
-                            "Bringing idle apps out of inactive state due to deviceIdleMode=false");
-                }
-                paroled = true;
-            } else if (deviceIdle) {
-                if (DEBUG) Slog.i(TAG, "Device idle, back to prison");
-                paroled = false;
-            } else {
-                return;
-            }
-        }
-        setAppIdleParoled(paroled);
-    }
-
     @Override
     public void reportEvent(UsageEvents.Event event, long elapsedRealtime, int userId) {
         if (!mAppIdleEnabled) return;
@@ -1038,11 +849,8 @@
     }
 
     @Override
-    public boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime,
+    public boolean isAppIdleFiltered(String packageName, int userId, long elapsedRealtime,
             boolean shouldObfuscateInstantApps) {
-        if (isParoledOrCharging()) {
-            return false;
-        }
         if (shouldObfuscateInstantApps &&
                 mInjector.isPackageEphemeral(userId, packageName)) {
             return false;
@@ -1388,15 +1196,6 @@
         }
     }
 
-    private void informParoleStateChanged() {
-        final boolean paroled = isParoledOrCharging();
-        synchronized (mPackageAccessListeners) {
-            for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
-                listener.onParoleStateChanged(paroled);
-            }
-        }
-    }
-
     @Override
     public void flushToDisk(int userId) {
         synchronized (mAppIdleLock) {
@@ -1517,18 +1316,6 @@
         TimeUtils.formatDuration(mCheckIdleIntervalMillis, pw);
         pw.println();
 
-        pw.print("  mAppIdleParoleIntervalMillis=");
-        TimeUtils.formatDuration(mAppIdleParoleIntervalMillis, pw);
-        pw.println();
-
-        pw.print("  mAppIdleParoleWindowMillis=");
-        TimeUtils.formatDuration(mAppIdleParoleWindowMillis, pw);
-        pw.println();
-
-        pw.print("  mAppIdleParoleDurationMillis=");
-        TimeUtils.formatDuration(mAppIdleParoleDurationMillis, pw);
-        pw.println();
-
         pw.print("  mStrongUsageTimeoutMillis=");
         TimeUtils.formatDuration(mStrongUsageTimeoutMillis, pw);
         pw.println();
@@ -1566,22 +1353,11 @@
         TimeUtils.formatDuration(mSystemUpdateUsageTimeoutMillis, pw);
         pw.println();
 
-        pw.print("  mStableChargingThresholdMillis=");
-        TimeUtils.formatDuration(mStableChargingThresholdMillis, pw);
-        pw.println();
-
         pw.println();
         pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
-        pw.print(" mAppIdleTempParoled="); pw.print(mAppIdleTempParoled);
-        pw.print(" mCharging="); pw.print(mCharging);
-        pw.print(" mChargingStable="); pw.print(mChargingStable);
-        pw.print(" mLastAppIdleParoledTime=");
-        TimeUtils.formatDuration(now - mLastAppIdleParoledTime, pw);
         pw.println();
         pw.print("mScreenThresholds="); pw.println(Arrays.toString(mAppStandbyScreenThresholds));
         pw.print("mElapsedThresholds="); pw.println(Arrays.toString(mAppStandbyElapsedThresholds));
-        pw.print("mStableChargingThresholdMillis=");
-        TimeUtils.formatDuration(mStableChargingThresholdMillis, pw);
         pw.println();
     }
 
@@ -1655,10 +1431,6 @@
             return buildFlag && runtimeFlag;
         }
 
-        boolean isCharging() {
-            return mContext.getSystemService(BatteryManager.class).isCharging();
-        }
-
         boolean isPowerSaveWhitelistExceptIdleApp(String packageName) throws RemoteException {
             return mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName);
         }
@@ -1748,15 +1520,6 @@
                     checkIdleStates(UserHandle.USER_ALL);
                     break;
 
-                case MSG_CHECK_PAROLE_TIMEOUT:
-                    checkParoleTimeout();
-                    break;
-
-                case MSG_PAROLE_END_TIMEOUT:
-                    if (DEBUG) Slog.d(TAG, "Ending parole");
-                    setAppIdleParoled(false);
-                    break;
-
                 case MSG_REPORT_CONTENT_PROVIDER_USAGE:
                     SomeArgs args = (SomeArgs) msg.obj;
                     reportContentProviderUsage((String) args.arg1, // authority name
@@ -1765,11 +1528,6 @@
                     args.recycle();
                     break;
 
-                case MSG_PAROLE_STATE_CHANGED:
-                    if (DEBUG) Slog.d(TAG, "Parole state: " + mAppIdleTempParoled
-                            + ", Charging state:" + mChargingStable);
-                    informParoleStateChanged();
-                    break;
                 case MSG_CHECK_PACKAGE_IDLE_STATE:
                     checkAndUpdateStandbyState((String) msg.obj, msg.arg1, msg.arg2,
                             mInjector.elapsedRealtime());
@@ -1788,10 +1546,6 @@
                     reportExemptedSyncStart((String) msg.obj, msg.arg1);
                     break;
 
-                case MSG_UPDATE_STABLE_CHARGING:
-                    updateChargingStableState();
-                    break;
-
                 default:
                     super.handleMessage(msg);
                     break;
@@ -1800,23 +1554,6 @@
         }
     };
 
-    private class DeviceStateReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            switch (intent.getAction()) {
-                case BatteryManager.ACTION_CHARGING:
-                    setChargingState(true);
-                    break;
-                case BatteryManager.ACTION_DISCHARGING:
-                    setChargingState(false);
-                    break;
-                case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED:
-                    onDeviceIdleModeChanged();
-                    break;
-            }
-        }
-    }
-
     private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder().build();
 
     private final ConnectivityManager.NetworkCallback mNetworkCallback
@@ -1824,7 +1561,6 @@
         @Override
         public void onAvailable(Network network) {
             mConnectivityManager.unregisterNetworkCallback(this);
-            checkParoleTimeout();
         }
     };
 
@@ -1851,9 +1587,6 @@
      * Observe settings changes for {@link Global#APP_IDLE_CONSTANTS}.
      */
     private class SettingsObserver extends ContentObserver {
-        private static final String KEY_PAROLE_INTERVAL = "parole_interval";
-        private static final String KEY_PAROLE_WINDOW = "parole_window";
-        private static final String KEY_PAROLE_DURATION = "parole_duration";
         private static final String KEY_SCREEN_TIME_THRESHOLDS = "screen_thresholds";
         private static final String KEY_ELAPSED_TIME_THRESHOLDS = "elapsed_thresholds";
         private static final String KEY_STRONG_USAGE_HOLD_DURATION = "strong_usage_duration";
@@ -1875,7 +1608,6 @@
                 "system_interaction_duration";
         private static final String KEY_INITIAL_FOREGROUND_SERVICE_START_HOLD_DURATION =
                 "initial_foreground_service_start_duration";
-        private static final String KEY_STABLE_CHARGING_THRESHOLD = "stable_charging_threshold";
         public static final long DEFAULT_STRONG_USAGE_TIMEOUT = 1 * ONE_HOUR;
         public static final long DEFAULT_NOTIFICATION_TIMEOUT = 12 * ONE_HOUR;
         public static final long DEFAULT_SYSTEM_UPDATE_TIMEOUT = 2 * ONE_HOUR;
@@ -1885,7 +1617,6 @@
         public static final long DEFAULT_EXEMPTED_SYNC_SCHEDULED_DOZE_TIMEOUT = 4 * ONE_HOUR;
         public static final long DEFAULT_EXEMPTED_SYNC_START_TIMEOUT = 10 * ONE_MINUTE;
         public static final long DEFAULT_UNEXEMPTED_SYNC_SCHEDULED_TIMEOUT = 10 * ONE_MINUTE;
-        public static final long DEFAULT_STABLE_CHARGING_THRESHOLD = 10 * ONE_MINUTE;
         public static final long DEFAULT_INITIAL_FOREGROUND_SERVICE_START_TIMEOUT = 30 * ONE_MINUTE;
 
         private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -1932,17 +1663,6 @@
 
             synchronized (mAppIdleLock) {
 
-                // Default: 24 hours between paroles
-                mAppIdleParoleIntervalMillis = mParser.getDurationMillis(KEY_PAROLE_INTERVAL,
-                        COMPRESS_TIME ? ONE_MINUTE * 10 : 24 * 60 * ONE_MINUTE);
-
-                // Default: 2 hours to wait on network
-                mAppIdleParoleWindowMillis = mParser.getDurationMillis(KEY_PAROLE_WINDOW,
-                        COMPRESS_TIME ? ONE_MINUTE * 2 : 2 * 60 * ONE_MINUTE);
-
-                mAppIdleParoleDurationMillis = mParser.getDurationMillis(KEY_PAROLE_DURATION,
-                        COMPRESS_TIME ? ONE_MINUTE : 10 * ONE_MINUTE); // 10 minutes
-
                 String screenThresholdsValue = mParser.getString(KEY_SCREEN_TIME_THRESHOLDS, null);
                 mAppStandbyScreenThresholds = parseLongArray(screenThresholdsValue,
                         SCREEN_TIME_THRESHOLDS);
@@ -1997,10 +1717,6 @@
                         KEY_INITIAL_FOREGROUND_SERVICE_START_HOLD_DURATION,
                         COMPRESS_TIME ? ONE_MINUTE :
                                 DEFAULT_INITIAL_FOREGROUND_SERVICE_START_TIMEOUT);
-
-                mStableChargingThresholdMillis = mParser.getDurationMillis(
-                        KEY_STABLE_CHARGING_THRESHOLD,
-                                COMPRESS_TIME ? ONE_MINUTE : DEFAULT_STABLE_CHARGING_THRESHOLD);
             }
 
             // Check if app_idle_enabled has changed. Do this after getting the rest of the settings
diff --git a/api/current.txt b/api/current.txt
index 1884055..3da03a0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2946,6 +2946,7 @@
     field public static final int FEEDBACK_SPOKEN = 1; // 0x1
     field public static final int FEEDBACK_VISUAL = 8; // 0x8
     field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
+    field public static final int FLAG_HANDLE_SHORTCUT = 2048; // 0x800
     field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
     field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
     field public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 256; // 0x100
@@ -3881,6 +3882,7 @@
     method public void setTitle(CharSequence);
     method public void setTitle(int);
     method @Deprecated public void setTitleColor(int);
+    method public boolean setTranslucent(boolean);
     method public void setTurnScreenOn(boolean);
     method public void setVisible(boolean);
     method public final void setVolumeControlStream(int);
@@ -4278,23 +4280,24 @@
     method @Deprecated public int checkOp(@NonNull String, int, @NonNull String);
     method @Deprecated public int checkOpNoThrow(@NonNull String, int, @NonNull String);
     method public void checkPackage(int, @NonNull String);
-    method public void finishOp(@NonNull String, int, @NonNull String);
+    method @Deprecated public void finishOp(@NonNull String, int, @NonNull String);
+    method public void finishOp(@NonNull String, int, @NonNull String, @Nullable String);
     method public boolean isOpActive(@NonNull String, int, @NonNull String);
     method @Deprecated public int noteOp(@NonNull String, int, @NonNull String);
-    method public int noteOp(@NonNull String, int, @Nullable String, @Nullable String);
+    method public int noteOp(@NonNull String, int, @Nullable String, @Nullable String, @Nullable String);
     method @Deprecated public int noteOpNoThrow(@NonNull String, int, @NonNull String);
-    method public int noteOpNoThrow(@NonNull String, int, @NonNull String, @Nullable String);
+    method public int noteOpNoThrow(@NonNull String, int, @NonNull String, @Nullable String, @Nullable String);
     method @Deprecated public int noteProxyOp(@NonNull String, @NonNull String);
-    method public int noteProxyOp(@NonNull String, @Nullable String, int, @Nullable String);
+    method public int noteProxyOp(@NonNull String, @Nullable String, int, @Nullable String, @Nullable String);
     method @Deprecated public int noteProxyOpNoThrow(@NonNull String, @NonNull String);
     method @Deprecated public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int);
-    method public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int, @Nullable String);
+    method public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int, @Nullable String, @Nullable String);
     method public static String permissionToOp(String);
     method public void setNotedAppOpsCollector(@Nullable android.app.AppOpsManager.AppOpsCollector);
     method @Deprecated public int startOp(@NonNull String, int, @NonNull String);
-    method public int startOp(@NonNull String, int, @Nullable String, @Nullable String);
+    method public int startOp(@NonNull String, int, @Nullable String, @NonNull String, @Nullable String);
     method @Deprecated public int startOpNoThrow(@NonNull String, int, @NonNull String);
-    method public int startOpNoThrow(@NonNull String, int, @NonNull String, @Nullable String);
+    method public int startOpNoThrow(@NonNull String, int, @NonNull String, @NonNull String, @Nullable String);
     method public void startWatchingActive(@NonNull String[], @NonNull java.util.concurrent.Executor, @NonNull android.app.AppOpsManager.OnOpActiveChangedListener);
     method public void startWatchingMode(@NonNull String, @Nullable String, @NonNull android.app.AppOpsManager.OnOpChangedListener);
     method public void startWatchingMode(@NonNull String, @Nullable String, int, @NonNull android.app.AppOpsManager.OnOpChangedListener);
@@ -4476,12 +4479,13 @@
 
   public final class AsyncNotedAppOp implements android.os.Parcelable {
     method public int describeContents();
+    method @Nullable public String getFeatureId();
     method @NonNull public String getMessage();
     method @Nullable public String getNotingPackageName();
     method @IntRange(from=0) public int getNotingUid();
     method @NonNull public String getOp();
     method @IntRange(from=0) public long getTime();
-    method public void writeToParcel(android.os.Parcel, int);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.AsyncNotedAppOp> CREATOR;
   }
 
@@ -5872,6 +5876,7 @@
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
     method public android.app.AutomaticZenRule getAutomaticZenRule(String);
     method public java.util.Map<java.lang.String,android.app.AutomaticZenRule> getAutomaticZenRules();
+    method @Nullable public android.app.NotificationManager.Policy getConsolidatedNotificationPolicy();
     method public final int getCurrentInterruptionFilter();
     method public int getImportance();
     method public android.app.NotificationChannel getNotificationChannel(String);
@@ -6299,6 +6304,7 @@
   }
 
   public final class SyncNotedAppOp {
+    method @Nullable public String getFeatureId();
     method @NonNull public String getOp();
   }
 
@@ -9775,6 +9781,7 @@
     method public abstract android.content.Context createContextForSplit(String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.Context createDeviceProtectedStorageContext();
     method public abstract android.content.Context createDisplayContext(@NonNull android.view.Display);
+    method @NonNull public android.content.Context createFeatureContext(@Nullable String);
     method public abstract android.content.Context createPackageContext(String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract String[] databaseList();
     method public abstract boolean deleteDatabase(String);
@@ -9806,6 +9813,7 @@
     method @Nullable public abstract java.io.File getExternalFilesDir(@Nullable String);
     method public abstract java.io.File[] getExternalFilesDirs(String);
     method @Deprecated public abstract java.io.File[] getExternalMediaDirs();
+    method @Nullable public String getFeatureId();
     method public abstract java.io.File getFileStreamPath(String);
     method public abstract java.io.File getFilesDir();
     method public java.util.concurrent.Executor getMainExecutor();
@@ -13771,7 +13779,9 @@
   public enum Bitmap.CompressFormat {
     enum_constant public static final android.graphics.Bitmap.CompressFormat JPEG;
     enum_constant public static final android.graphics.Bitmap.CompressFormat PNG;
-    enum_constant public static final android.graphics.Bitmap.CompressFormat WEBP;
+    enum_constant @Deprecated public static final android.graphics.Bitmap.CompressFormat WEBP;
+    enum_constant public static final android.graphics.Bitmap.CompressFormat WEBP_LOSSLESS;
+    enum_constant public static final android.graphics.Bitmap.CompressFormat WEBP_LOSSY;
   }
 
   public enum Bitmap.Config {
@@ -23138,6 +23148,7 @@
     method @Deprecated public void clearTestProviderStatus(@NonNull String);
     method @NonNull public java.util.List<java.lang.String> getAllProviders();
     method @Nullable public String getBestProvider(@NonNull android.location.Criteria, boolean);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
     method @Nullable public String getGnssHardwareModelName();
     method public int getGnssYearOfHardware();
     method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
@@ -24651,6 +24662,7 @@
     field public static final int DolbyVisionLevelUhd30 = 64; // 0x40
     field public static final int DolbyVisionLevelUhd48 = 128; // 0x80
     field public static final int DolbyVisionLevelUhd60 = 256; // 0x100
+    field public static final int DolbyVisionProfileDvav110 = 1024; // 0x400
     field public static final int DolbyVisionProfileDvavPen = 2; // 0x2
     field public static final int DolbyVisionProfileDvavPer = 1; // 0x1
     field public static final int DolbyVisionProfileDvavSe = 512; // 0x200
@@ -25417,22 +25429,22 @@
   public class MediaMetadataRetriever implements java.lang.AutoCloseable {
     ctor public MediaMetadataRetriever();
     method public void close();
-    method public String extractMetadata(int);
-    method public byte[] getEmbeddedPicture();
-    method public android.graphics.Bitmap getFrameAtIndex(int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
-    method public android.graphics.Bitmap getFrameAtIndex(int);
-    method public android.graphics.Bitmap getFrameAtTime(long, int);
-    method public android.graphics.Bitmap getFrameAtTime(long, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
-    method public android.graphics.Bitmap getFrameAtTime(long);
-    method public android.graphics.Bitmap getFrameAtTime();
+    method @Nullable public String extractMetadata(int);
+    method @Nullable public byte[] getEmbeddedPicture();
+    method @Nullable public android.graphics.Bitmap getFrameAtIndex(int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
+    method @Nullable public android.graphics.Bitmap getFrameAtIndex(int);
+    method @Nullable public android.graphics.Bitmap getFrameAtTime(long, int);
+    method @Nullable public android.graphics.Bitmap getFrameAtTime(long, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
+    method @Nullable public android.graphics.Bitmap getFrameAtTime(long);
+    method @Nullable public android.graphics.Bitmap getFrameAtTime();
     method @NonNull public java.util.List<android.graphics.Bitmap> getFramesAtIndex(int, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
     method @NonNull public java.util.List<android.graphics.Bitmap> getFramesAtIndex(int, int);
-    method public android.graphics.Bitmap getImageAtIndex(int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
-    method public android.graphics.Bitmap getImageAtIndex(int);
-    method public android.graphics.Bitmap getPrimaryImage(@NonNull android.media.MediaMetadataRetriever.BitmapParams);
-    method public android.graphics.Bitmap getPrimaryImage();
-    method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int);
-    method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
+    method @Nullable public android.graphics.Bitmap getImageAtIndex(int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
+    method @Nullable public android.graphics.Bitmap getImageAtIndex(int);
+    method @Nullable public android.graphics.Bitmap getPrimaryImage(@NonNull android.media.MediaMetadataRetriever.BitmapParams);
+    method @Nullable public android.graphics.Bitmap getPrimaryImage();
+    method @Nullable public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int);
+    method @Nullable public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
     method public void release();
     method public void setDataSource(String) throws java.lang.IllegalArgumentException;
     method public void setDataSource(String, java.util.Map<java.lang.String,java.lang.String>) throws java.lang.IllegalArgumentException;
@@ -28920,7 +28932,9 @@
     method @NonNull public static android.net.MacAddress fromBytes(@NonNull byte[]);
     method @NonNull public static android.net.MacAddress fromString(@NonNull String);
     method public int getAddressType();
+    method @Nullable public java.net.Inet6Address getLinkLocalIpv6FromEui48Mac();
     method public boolean isLocallyAssigned();
+    method public boolean matches(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress);
     method @NonNull public byte[] toByteArray();
     method @NonNull public String toOuiString();
     method public void writeToParcel(android.os.Parcel, int);
@@ -29971,6 +29985,7 @@
     method @Deprecated public int addNetwork(android.net.wifi.WifiConfiguration);
     method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int addNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
     method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void addScanResultsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.ScanResultsListener);
     method public static int calculateSignalLevel(int, int);
     method @Deprecated public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
     method public static int compareSignalLevel(int, int);
@@ -30006,6 +30021,7 @@
     method @Deprecated public boolean removeNetwork(int);
     method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int removeNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
     method @Deprecated @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", "android.permission.NETWORK_CARRIER_PROVISIONING"}) public void removePasspointConfiguration(String);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void removeScanResultsListener(@NonNull android.net.wifi.WifiManager.ScanResultsListener);
     method @Deprecated public boolean saveConfiguration();
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(String, boolean);
@@ -30081,6 +30097,10 @@
     method public void setReferenceCounted(boolean);
   }
 
+  public static interface WifiManager.ScanResultsListener {
+    method public void onScanResultsAvailable();
+  }
+
   public class WifiManager.WifiLock {
     method public void acquire();
     method public boolean isHeld();
@@ -30132,6 +30152,7 @@
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsHiddenSsid(boolean);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsMetered(boolean);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsUserInteractionRequired(boolean);
+    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPasspointConfig(@NonNull android.net.wifi.hotspot2.PasspointConfiguration);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPriority(@IntRange(from=0) int);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setSsid(@NonNull String);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
@@ -38281,6 +38302,7 @@
     field public static final String COLUMN_MIME_TYPE = "mime_type";
     field public static final String COLUMN_SIZE = "_size";
     field public static final String COLUMN_SUMMARY = "summary";
+    field public static final int FLAG_DIR_BLOCKS_TREE = 32768; // 0x8000
     field public static final int FLAG_DIR_PREFERS_GRID = 16; // 0x10
     field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 32; // 0x20
     field public static final int FLAG_DIR_SUPPORTS_CREATE = 8; // 0x8
@@ -38499,16 +38521,17 @@
 
   public static final class MediaStore.Audio {
     ctor public MediaStore.Audio();
-    method public static String keyFor(String);
+    method @Deprecated @Nullable public static String keyFor(@Nullable String);
   }
 
   public static interface MediaStore.Audio.AlbumColumns {
     field public static final String ALBUM = "album";
     field @Deprecated public static final String ALBUM_ART = "album_art";
     field public static final String ALBUM_ID = "album_id";
-    field public static final String ALBUM_KEY = "album_key";
+    field @Deprecated public static final String ALBUM_KEY = "album_key";
     field public static final String ARTIST = "artist";
     field public static final String ARTIST_ID = "artist_id";
+    field @Deprecated public static final String ARTIST_KEY = "artist_key";
     field public static final String FIRST_YEAR = "minyear";
     field public static final String LAST_YEAR = "maxyear";
     field public static final String NUMBER_OF_SONGS = "numsongs";
@@ -38527,7 +38550,7 @@
 
   public static interface MediaStore.Audio.ArtistColumns {
     field public static final String ARTIST = "artist";
-    field public static final String ARTIST_KEY = "artist_key";
+    field @Deprecated public static final String ARTIST_KEY = "artist_key";
     field public static final String NUMBER_OF_ALBUMS = "number_of_albums";
     field public static final String NUMBER_OF_TRACKS = "number_of_tracks";
   }
@@ -38550,19 +38573,23 @@
   public static interface MediaStore.Audio.AudioColumns extends android.provider.MediaStore.MediaColumns {
     field public static final String ALBUM = "album";
     field public static final String ALBUM_ID = "album_id";
-    field public static final String ALBUM_KEY = "album_key";
+    field @Deprecated public static final String ALBUM_KEY = "album_key";
     field public static final String ARTIST = "artist";
     field public static final String ARTIST_ID = "artist_id";
-    field public static final String ARTIST_KEY = "artist_key";
+    field @Deprecated public static final String ARTIST_KEY = "artist_key";
     field public static final String BOOKMARK = "bookmark";
     field public static final String COMPOSER = "composer";
+    field public static final String GENRE = "genre";
+    field public static final String GENRE_ID = "genre_id";
+    field @Deprecated public static final String GENRE_KEY = "genre_key";
     field public static final String IS_ALARM = "is_alarm";
     field public static final String IS_AUDIOBOOK = "is_audiobook";
     field public static final String IS_MUSIC = "is_music";
     field public static final String IS_NOTIFICATION = "is_notification";
     field public static final String IS_PODCAST = "is_podcast";
     field public static final String IS_RINGTONE = "is_ringtone";
-    field public static final String TITLE_KEY = "title_key";
+    field @Deprecated public static final String TITLE_KEY = "title_key";
+    field public static final String TITLE_RESOURCE_URI = "title_resource_uri";
     field public static final String TRACK = "track";
     field public static final String YEAR = "year";
   }
@@ -40849,7 +40876,7 @@
     field public static final String EXTRA_KEY_ALIAS = "android.security.extra.KEY_ALIAS";
     field public static final String EXTRA_NAME = "name";
     field public static final String EXTRA_PKCS12 = "PKCS12";
-    field public static final String KEY_ALIAS_SELECTION_DENIED = "alias-selection-denied-ef829e15-210a-409d-96c9-ee684fc41972";
+    field public static final String KEY_ALIAS_SELECTION_DENIED = "android:alias-selection-denied";
   }
 
   public interface KeyChainAliasCallback {
@@ -41910,6 +41937,7 @@
     field public static final String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
     field public static final String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES";
     field public static final String META_DATA_ACTIVE_TILE = "android.service.quicksettings.ACTIVE_TILE";
+    field public static final String META_DATA_BOOLEAN_TILE = "android.service.quicksettings.BOOLEAN_TILE";
   }
 
 }
@@ -43458,8 +43486,10 @@
     method public final int getState();
     method public final android.telecom.StatusHints getStatusHints();
     method public final android.telecom.Connection.VideoProvider getVideoProvider();
+    method public final int getVideoState();
     method public void handleRttUpgradeResponse(@Nullable android.telecom.Connection.RttTextStream);
     method public final boolean isRingbackRequested();
+    method public final void notifyConferenceMergeFailed();
     method public void onAbort();
     method public void onAnswer(int);
     method public void onAnswer();
@@ -43538,8 +43568,15 @@
     field public static final int CAPABILITY_SUPPORT_DEFLECT = 33554432; // 0x2000000
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
+    field public static final String EVENT_CALL_HOLD_FAILED = "android.telecom.event.CALL_HOLD_FAILED";
     field public static final String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
     field public static final String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
+    field public static final String EVENT_CALL_REMOTELY_HELD = "android.telecom.event.CALL_REMOTELY_HELD";
+    field public static final String EVENT_CALL_REMOTELY_UNHELD = "android.telecom.event.CALL_REMOTELY_UNHELD";
+    field public static final String EVENT_MERGE_COMPLETE = "android.telecom.event.MERGE_COMPLETE";
+    field public static final String EVENT_MERGE_START = "android.telecom.event.MERGE_START";
+    field public static final String EVENT_ON_HOLD_TONE_END = "android.telecom.event.ON_HOLD_TONE_END";
+    field public static final String EVENT_ON_HOLD_TONE_START = "android.telecom.event.ON_HOLD_TONE_START";
     field public static final String EVENT_RTT_AUDIO_INDICATION_CHANGED = "android.telecom.event.RTT_AUDIO_INDICATION_CHANGED";
     field public static final String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL";
     field public static final String EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME = "android.telecom.extra.ANSWERING_DROPS_FG_CALL_APP_NAME";
@@ -43549,9 +43586,12 @@
     field public static final String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
     field public static final String EXTRA_SIP_INVITE = "android.telecom.extra.SIP_INVITE";
     field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20
+    field public static final int PROPERTY_HIGH_DEF_AUDIO = 4; // 0x4
     field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10
     field public static final int PROPERTY_IS_RTT = 256; // 0x100
+    field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1024; // 0x400
     field public static final int PROPERTY_SELF_MANAGED = 128; // 0x80
+    field public static final int PROPERTY_WIFI = 8; // 0x8
     field public static final int STATE_ACTIVE = 4; // 0x4
     field public static final int STATE_DIALING = 3; // 0x3
     field public static final int STATE_DISCONNECTED = 6; // 0x6
@@ -44248,9 +44288,11 @@
     field public static final String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
     field public static final String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long";
     field public static final String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
+    field public static final String KEY_DEFAULT_VM_NUMBER_ROAMING_AND_IMS_UNREGISTERED_STRING = "default_vm_number_roaming_and_ims_unregistered_string";
     field public static final String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
     field public static final String KEY_DIAL_STRING_REPLACE_STRING_ARRAY = "dial_string_replace_string_array";
     field public static final String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
+    field public static final String KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY = "disconnect_cause_play_busytone_int_array";
     field public static final String KEY_DISPLAY_HD_AUDIO_PROPERTY_BOOL = "display_hd_audio_property_bool";
     field public static final String KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL = "drop_video_call_when_answering_audio_call_bool";
     field public static final String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
@@ -44452,6 +44494,8 @@
   public abstract class CellInfo implements android.os.Parcelable {
     method public int describeContents();
     method public int getCellConnectionStatus();
+    method @NonNull public abstract android.telephony.CellIdentity getCellIdentity();
+    method @NonNull public abstract android.telephony.CellSignalStrength getCellSignalStrength();
     method public long getTimeStamp();
     method public boolean isRegistered();
     field public static final int CONNECTION_NONE = 0; // 0x0
@@ -44596,6 +44640,7 @@
     method public int describeContents();
     method public int getAsuLevel();
     method public int getDbm();
+    method public int getEcNo();
     method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthWcdma> CREATOR;
@@ -45101,6 +45146,7 @@
     method public long getDataLimitBytes();
     method public long getDataUsageBytes();
     method public long getDataUsageTime();
+    method @Nullable public int[] getNetworkTypes();
     method @Nullable public CharSequence getSummary();
     method @Nullable public CharSequence getTitle();
     method public void writeToParcel(android.os.Parcel, int);
@@ -45120,6 +45166,7 @@
     method public static android.telephony.SubscriptionPlan.Builder createRecurring(java.time.ZonedDateTime, java.time.Period);
     method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int);
     method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long);
+    method @NonNull public android.telephony.SubscriptionPlan.Builder setNetworkTypes(@Nullable int[]);
     method public android.telephony.SubscriptionPlan.Builder setSummary(@Nullable CharSequence);
     method public android.telephony.SubscriptionPlan.Builder setTitle(@Nullable CharSequence);
   }
@@ -50216,14 +50263,14 @@
   }
 
   public static interface SurfaceHolder.Callback {
-    method public void surfaceChanged(android.view.SurfaceHolder, int, int, int);
-    method public void surfaceCreated(android.view.SurfaceHolder);
-    method public void surfaceDestroyed(android.view.SurfaceHolder);
+    method public void surfaceChanged(@NonNull android.view.SurfaceHolder, int, @IntRange(from=0) int, @IntRange(from=0) int);
+    method public void surfaceCreated(@NonNull android.view.SurfaceHolder);
+    method public void surfaceDestroyed(@NonNull android.view.SurfaceHolder);
   }
 
   public static interface SurfaceHolder.Callback2 extends android.view.SurfaceHolder.Callback {
-    method public void surfaceRedrawNeeded(android.view.SurfaceHolder);
-    method public default void surfaceRedrawNeededAsync(android.view.SurfaceHolder, Runnable);
+    method public void surfaceRedrawNeeded(@NonNull android.view.SurfaceHolder);
+    method public default void surfaceRedrawNeededAsync(@NonNull android.view.SurfaceHolder, @NonNull Runnable);
   }
 
   public class SurfaceView extends android.view.View {
diff --git a/api/lint-baseline.txt b/api/lint-baseline.txt
new file mode 100644
index 0000000..2ca8cf4
--- /dev/null
+++ b/api/lint-baseline.txt
@@ -0,0 +1,1179 @@
+// Baseline format: 1.0
+AcronymName: android.system.ErrnoException#rethrowAsIOException():
+    
+
+
+ActionValue: android.provider.Settings#ACTION_CONDITION_PROVIDER_SETTINGS:
+    
+
+
+AllUpper: android.media.MediaCodecInfo.CodecCapabilities#FEATURE_LowLatency:
+    
+
+
+ArrayReturn: android.app.Notification.MessagingStyle.Message#getMessagesFromBundleArray(android.os.Parcelable[]) parameter #0:
+    
+ArrayReturn: android.content.ContentProviderOperation#resolveExtrasBackReferences(android.content.ContentProviderResult[], int) parameter #0:
+    
+
+
+BroadcastBehavior: android.app.AlarmManager#ACTION_NEXT_ALARM_CLOCK_CHANGED:
+    
+BroadcastBehavior: android.app.admin.DevicePolicyManager#ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED:
+    
+BroadcastBehavior: android.app.admin.DevicePolicyManager#ACTION_MANAGED_PROFILE_PROVISIONED:
+    
+BroadcastBehavior: android.bluetooth.BluetoothAdapter#ACTION_DISCOVERY_FINISHED:
+    
+BroadcastBehavior: android.bluetooth.BluetoothAdapter#ACTION_DISCOVERY_STARTED:
+    
+BroadcastBehavior: android.bluetooth.BluetoothAdapter#ACTION_LOCAL_NAME_CHANGED:
+    
+BroadcastBehavior: android.bluetooth.BluetoothAdapter#ACTION_SCAN_MODE_CHANGED:
+    
+BroadcastBehavior: android.bluetooth.BluetoothAdapter#ACTION_STATE_CHANGED:
+    
+BroadcastBehavior: android.bluetooth.BluetoothDevice#ACTION_ACL_CONNECTED:
+    
+BroadcastBehavior: android.bluetooth.BluetoothDevice#ACTION_ACL_DISCONNECTED:
+    
+BroadcastBehavior: android.bluetooth.BluetoothDevice#ACTION_ACL_DISCONNECT_REQUESTED:
+    
+BroadcastBehavior: android.bluetooth.BluetoothDevice#ACTION_BOND_STATE_CHANGED:
+    
+BroadcastBehavior: android.bluetooth.BluetoothDevice#ACTION_CLASS_CHANGED:
+    
+BroadcastBehavior: android.bluetooth.BluetoothDevice#ACTION_FOUND:
+    
+BroadcastBehavior: android.bluetooth.BluetoothDevice#ACTION_NAME_CHANGED:
+    
+BroadcastBehavior: android.bluetooth.BluetoothDevice#ACTION_PAIRING_REQUEST:
+    
+BroadcastBehavior: android.bluetooth.BluetoothDevice#ACTION_UUID:
+    
+BroadcastBehavior: android.content.Intent#ACTION_AIRPLANE_MODE_CHANGED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_CHANGED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_LOW:
+    
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_OKAY:
+    
+BroadcastBehavior: android.content.Intent#ACTION_CAMERA_BUTTON:
+    
+BroadcastBehavior: android.content.Intent#ACTION_CLOSE_SYSTEM_DIALOGS:
+    
+BroadcastBehavior: android.content.Intent#ACTION_CONFIGURATION_CHANGED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_DATE_CHANGED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_DEVICE_STORAGE_LOW:
+    
+BroadcastBehavior: android.content.Intent#ACTION_DEVICE_STORAGE_OK:
+    
+BroadcastBehavior: android.content.Intent#ACTION_DOCK_EVENT:
+    
+BroadcastBehavior: android.content.Intent#ACTION_DREAMING_STARTED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_DREAMING_STOPPED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
+    
+BroadcastBehavior: android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
+    
+BroadcastBehavior: android.content.Intent#ACTION_GTALK_SERVICE_CONNECTED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_GTALK_SERVICE_DISCONNECTED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_HEADSET_PLUG:
+    
+BroadcastBehavior: android.content.Intent#ACTION_INPUT_METHOD_CHANGED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_LOCALE_CHANGED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_LOCKED_BOOT_COMPLETED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MANAGE_PACKAGE_STORAGE:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_BAD_REMOVAL:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_BUTTON:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_CHECKING:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_EJECT:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_MOUNTED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_NOFS:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_REMOVED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_FINISHED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_SCAN_FILE:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_STARTED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SHARED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_UNMOUNTABLE:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_UNMOUNTED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_REPLACED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_SUSPENDED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_UNSUSPENDED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_NEW_OUTGOING_CALL:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGES_SUSPENDED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGES_UNSUSPENDED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_ADDED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_CHANGED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_DATA_CLEARED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_FIRST_LAUNCH:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_FULLY_REMOVED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_INSTALL:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_NEEDS_VERIFICATION:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_REMOVED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_REPLACED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_RESTARTED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_VERIFIED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_POWER_CONNECTED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_POWER_DISCONNECTED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_PROVIDER_CHANGED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_REBOOT:
+    
+BroadcastBehavior: android.content.Intent#ACTION_SCREEN_OFF:
+    
+BroadcastBehavior: android.content.Intent#ACTION_SCREEN_ON:
+    
+BroadcastBehavior: android.content.Intent#ACTION_SHUTDOWN:
+    
+BroadcastBehavior: android.content.Intent#ACTION_TIMEZONE_CHANGED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_TIME_CHANGED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_TIME_TICK:
+    
+BroadcastBehavior: android.content.Intent#ACTION_UID_REMOVED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_UMS_CONNECTED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_UMS_DISCONNECTED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_USER_PRESENT:
+    
+BroadcastBehavior: android.content.Intent#ACTION_USER_UNLOCKED:
+    
+BroadcastBehavior: android.content.Intent#ACTION_WALLPAPER_CHANGED:
+    
+BroadcastBehavior: android.content.pm.PackageInstaller#ACTION_SESSION_COMMITTED:
+    
+BroadcastBehavior: android.content.pm.PackageInstaller#ACTION_SESSION_UPDATED:
+    
+BroadcastBehavior: android.hardware.Camera#ACTION_NEW_PICTURE:
+    
+BroadcastBehavior: android.hardware.Camera#ACTION_NEW_VIDEO:
+    
+BroadcastBehavior: android.hardware.input.InputManager#ACTION_QUERY_KEYBOARD_LAYOUTS:
+    
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_ACCESSORY_DETACHED:
+    
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_DEVICE_DETACHED:
+    
+BroadcastBehavior: android.media.AudioManager#ACTION_HDMI_AUDIO_PLUG:
+    
+BroadcastBehavior: android.media.AudioManager#ACTION_HEADSET_PLUG:
+    
+BroadcastBehavior: android.media.AudioManager#ACTION_MICROPHONE_MUTE_CHANGED:
+    
+BroadcastBehavior: android.media.AudioManager#ACTION_SPEAKERPHONE_STATE_CHANGED:
+    
+BroadcastBehavior: android.media.tv.TvContract#ACTION_INITIALIZE_PROGRAMS:
+    
+BroadcastBehavior: android.media.tv.TvContract#ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT:
+    
+BroadcastBehavior: android.media.tv.TvContract#ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED:
+    
+BroadcastBehavior: android.media.tv.TvContract#ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED:
+    
+BroadcastBehavior: android.net.ConnectivityManager#ACTION_BACKGROUND_DATA_SETTING_CHANGED:
+    
+BroadcastBehavior: android.net.Proxy#PROXY_CHANGE_ACTION:
+    
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_ADAPTER_STATE_CHANGED:
+    
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED:
+    
+BroadcastBehavior: android.os.DropBoxManager#ACTION_DROPBOX_ENTRY_ADDED:
+    
+BroadcastBehavior: android.provider.CalendarContract#ACTION_EVENT_REMINDER:
+    
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#DATA_SMS_RECEIVED_ACTION:
+    
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SECRET_CODE_ACTION:
+    
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SIM_FULL_ACTION:
+    
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_CB_RECEIVED_ACTION:
+    
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_DELIVER_ACTION:
+    
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_RECEIVED_ACTION:
+    
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_REJECTED_ACTION:
+    
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION:
+    
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#WAP_PUSH_DELIVER_ACTION:
+    
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#WAP_PUSH_RECEIVED_ACTION:
+    
+BroadcastBehavior: android.security.KeyChain#ACTION_KEYCHAIN_CHANGED:
+    
+BroadcastBehavior: android.security.KeyChain#ACTION_KEY_ACCESS_CHANGED:
+    
+BroadcastBehavior: android.security.KeyChain#ACTION_STORAGE_CHANGED:
+    
+BroadcastBehavior: android.security.KeyChain#ACTION_TRUST_STORE_CHANGED:
+    
+BroadcastBehavior: android.speech.tts.TextToSpeech#ACTION_TTS_QUEUE_PROCESSING_COMPLETED:
+    
+BroadcastBehavior: android.speech.tts.TextToSpeech.Engine#ACTION_TTS_DATA_INSTALLED:
+    
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED:
+    
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_DEFAULT_SUBSCRIPTION_CHANGED:
+    
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_REFRESH_SUBSCRIPTION_PLANS:
+    
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SECRET_CODE:
+    
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED:
+    
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED:
+    
+BroadcastBehavior: android.telephony.euicc.EuiccManager#ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE:
+    
+
+
+CompileTimeConstant: android.icu.util.JapaneseCalendar#REIWA:
+    
+
+
+DeprecationMismatch: android.accounts.AccountManager#newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, String[], boolean, String, String, String[], android.os.Bundle):
+    
+DeprecationMismatch: android.app.Activity#enterPictureInPictureMode():
+    
+DeprecationMismatch: android.app.Instrumentation#startAllocCounting():
+    
+DeprecationMismatch: android.app.Instrumentation#stopAllocCounting():
+    
+DeprecationMismatch: android.app.Notification#bigContentView:
+    
+DeprecationMismatch: android.app.Notification#contentView:
+    
+DeprecationMismatch: android.app.Notification#headsUpContentView:
+    
+DeprecationMismatch: android.app.Notification#tickerView:
+    
+DeprecationMismatch: android.app.Notification.Action.Builder#Builder(int, CharSequence, android.app.PendingIntent):
+    
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getCancelLabel():
+    
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getConfirmLabel():
+    
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getInProgressLabel():
+    
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setCancelLabel(CharSequence):
+    
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setConfirmLabel(CharSequence):
+    
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setInProgressLabel(CharSequence):
+    
+DeprecationMismatch: android.app.Notification.Builder#setContent(android.widget.RemoteViews):
+    
+DeprecationMismatch: android.app.Notification.Builder#setTicker(CharSequence, android.widget.RemoteViews):
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#getContentIcon():
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#getContentIconGravity():
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#getCustomContentHeight():
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#getCustomSizePreset():
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#getGravity():
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintAvoidBackgroundClipping():
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintHideIcon():
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintScreenTimeout():
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintShowBackgroundOnly():
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#setContentIcon(int):
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#setContentIconGravity(int):
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#setCustomContentHeight(int):
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#setCustomSizePreset(int):
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#setGravity(int):
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintAvoidBackgroundClipping(boolean):
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintHideIcon(boolean):
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintScreenTimeout(int):
+    
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintShowBackgroundOnly(boolean):
+    
+DeprecationMismatch: android.content.ContextWrapper#clearWallpaper():
+    
+DeprecationMismatch: android.content.ContextWrapper#getWallpaper():
+    
+DeprecationMismatch: android.content.ContextWrapper#getWallpaperDesiredMinimumHeight():
+    
+DeprecationMismatch: android.content.ContextWrapper#getWallpaperDesiredMinimumWidth():
+    
+DeprecationMismatch: android.content.ContextWrapper#peekWallpaper():
+    
+DeprecationMismatch: android.content.ContextWrapper#removeStickyBroadcast(android.content.Intent):
+    
+DeprecationMismatch: android.content.ContextWrapper#removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle):
+    
+DeprecationMismatch: android.content.ContextWrapper#sendStickyBroadcast(android.content.Intent):
+    
+DeprecationMismatch: android.content.ContextWrapper#sendStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle):
+    
+DeprecationMismatch: android.content.ContextWrapper#sendStickyOrderedBroadcast(android.content.Intent, android.content.BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle):
+    
+DeprecationMismatch: android.content.ContextWrapper#sendStickyOrderedBroadcastAsUser(android.content.Intent, android.os.UserHandle, android.content.BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle):
+    
+DeprecationMismatch: android.content.ContextWrapper#setWallpaper(android.graphics.Bitmap):
+    
+DeprecationMismatch: android.content.ContextWrapper#setWallpaper(java.io.InputStream):
+    
+DeprecationMismatch: android.database.CursorWrapper#deactivate():
+    
+DeprecationMismatch: android.database.CursorWrapper#requery():
+    
+DeprecationMismatch: android.graphics.ComposeShader#ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode):
+    
+DeprecationMismatch: android.graphics.PixelFormat#A_8:
+    
+DeprecationMismatch: android.graphics.PixelFormat#LA_88:
+    
+DeprecationMismatch: android.graphics.PixelFormat#L_8:
+    
+DeprecationMismatch: android.graphics.PixelFormat#RGBA_4444:
+    
+DeprecationMismatch: android.graphics.PixelFormat#RGBA_5551:
+    
+DeprecationMismatch: android.graphics.PixelFormat#RGB_332:
+    
+DeprecationMismatch: android.net.wifi.WifiManager#EXTRA_BSSID:
+    
+DeprecationMismatch: android.net.wifi.WifiManager#EXTRA_WIFI_INFO:
+    
+DeprecationMismatch: android.opengl.EGL14#eglCreatePixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int):
+    
+DeprecationMismatch: android.opengl.GLES20#GL_STENCIL_INDEX:
+    
+DeprecationMismatch: android.opengl.GLSurfaceView#surfaceRedrawNeeded(android.view.SurfaceHolder):
+    
+DeprecationMismatch: android.os.UserManager#setUserRestrictions(android.os.Bundle):
+    
+DeprecationMismatch: android.os.UserManager#setUserRestrictions(android.os.Bundle, android.os.UserHandle):
+    
+DeprecationMismatch: android.provider.Contacts.People#markAsContacted(android.content.ContentResolver, long):
+    
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_X:
+    
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_Y:
+    
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_Z:
+    
+DeprecationMismatch: android.speech.tts.TextToSpeech#areDefaultsEnforced():
+    
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_12HOUR:
+    
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_24HOUR:
+    
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_AMPM:
+    
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_MIDNIGHT:
+    
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_NOON:
+    
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_NOON_MIDNIGHT:
+    
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_NO_NOON_MIDNIGHT:
+    
+DeprecationMismatch: android.view.ViewGroup.LayoutParams#FILL_PARENT:
+    
+DeprecationMismatch: android.view.Window#setTitleColor(int):
+    
+DeprecationMismatch: android.view.accessibility.AccessibilityEvent#MAX_TEXT_LENGTH:
+    
+DeprecationMismatch: android.webkit.WebSettings#getSaveFormData():
+    
+DeprecationMismatch: android.webkit.WebView#shouldDelayChildPressedState():
+    
+DeprecationMismatch: android.webkit.WebViewDatabase#clearFormData():
+    
+DeprecationMismatch: android.webkit.WebViewDatabase#hasFormData():
+    
+DeprecationMismatch: javax.microedition.khronos.egl.EGL10#eglCreatePixmapSurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, Object, int[]):
+    
+
+
+GenericException: android.content.res.loader.ResourcesProvider#finalize():
+    Methods must not throw generic exceptions (`java.lang.Throwable`)
+
+
+HiddenSuperclass: android.content.res.ColorStateList:
+    
+HiddenSuperclass: android.graphics.Canvas:
+    
+HiddenSuperclass: android.graphics.RecordingCanvas:
+    
+HiddenSuperclass: android.hardware.biometrics.BiometricPrompt.AuthenticationCallback:
+    
+HiddenSuperclass: android.hardware.biometrics.BiometricPrompt.AuthenticationResult:
+    
+HiddenSuperclass: android.hardware.biometrics.BiometricPrompt.CryptoObject:
+    
+HiddenSuperclass: android.hardware.fingerprint.FingerprintManager.AuthenticationCallback:
+    
+HiddenSuperclass: android.hardware.fingerprint.FingerprintManager.CryptoObject:
+    
+HiddenSuperclass: android.media.AudioTrack:
+    
+HiddenSuperclass: android.media.MediaPlayer:
+    
+HiddenSuperclass: android.media.SoundPool:
+    
+HiddenSuperclass: android.service.autofill.CharSequenceTransformation:
+    
+HiddenSuperclass: android.service.autofill.DateTransformation:
+    
+HiddenSuperclass: android.service.autofill.DateValueSanitizer:
+    
+HiddenSuperclass: android.service.autofill.ImageTransformation:
+    
+HiddenSuperclass: android.service.autofill.LuhnChecksumValidator:
+    
+HiddenSuperclass: android.service.autofill.RegexValidator:
+    
+HiddenSuperclass: android.service.autofill.TextValueSanitizer:
+    
+HiddenSuperclass: android.service.autofill.VisibilitySetterAction:
+    
+HiddenSuperclass: android.util.StatsLog:
+    
+
+
+MissingNullability: android.app.AsyncNotedAppOp#equals(Object) parameter #0:
+    
+MissingNullability: android.app.AsyncNotedAppOp#writeToParcel(android.os.Parcel, int) parameter #0:
+    
+MissingNullability: android.app.SyncNotedAppOp#equals(Object) parameter #0:
+    
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS:
+    
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#ELYMAIC:
+    
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#NANDINAGARI:
+    
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#NYIAKENG_PUACHUE_HMONG:
+    
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#OTTOMAN_SIYAQ_NUMBERS:
+    
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#SMALL_KANA_EXTENSION:
+    
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A:
+    
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#TAMIL_SUPPLEMENT:
+    
+MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#WANCHO:
+    
+MissingNullability: android.icu.text.DateTimePatternGenerator#getFieldDisplayName(int, android.icu.text.DateTimePatternGenerator.DisplayWidth):
+    
+MissingNullability: android.icu.text.DateTimePatternGenerator#getFieldDisplayName(int, android.icu.text.DateTimePatternGenerator.DisplayWidth) parameter #1:
+    
+MissingNullability: android.icu.util.VersionInfo#UNICODE_12_0:
+    
+MissingNullability: android.icu.util.VersionInfo#UNICODE_12_1:
+    
+MissingNullability: android.media.MediaMetadataRetriever#getFrameAtTime(long, int, android.media.MediaMetadataRetriever.BitmapParams):
+    
+MissingNullability: android.media.MediaMetadataRetriever#getScaledFrameAtTime(long, int, int, int, android.media.MediaMetadataRetriever.BitmapParams):
+    
+
+
+RequiresPermission: android.accounts.AccountManager#getAccountsByTypeAndFeatures(String, String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler):
+    
+RequiresPermission: android.accounts.AccountManager#hasFeatures(android.accounts.Account, String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
+    
+RequiresPermission: android.app.AlarmManager#setTime(long):
+    
+RequiresPermission: android.app.AppOpsManager#isOpActive(String, int, String):
+    
+RequiresPermission: android.app.AppOpsManager#startWatchingActive(String[], java.util.concurrent.Executor, android.app.AppOpsManager.OnOpActiveChangedListener):
+    
+RequiresPermission: android.app.DownloadManager.Request#setDestinationInExternalPublicDir(String, String):
+    
+RequiresPermission: android.app.DownloadManager.Request#setDestinationUri(android.net.Uri):
+    
+RequiresPermission: android.app.DownloadManager.Request#setNotificationVisibility(int):
+    
+RequiresPermission: android.app.DownloadManager.Request#setShowRunningNotification(boolean):
+    
+RequiresPermission: android.app.Notification.Builder#setFullScreenIntent(android.app.PendingIntent, boolean):
+    
+RequiresPermission: android.app.Service#startForeground(int, android.app.Notification):
+    
+RequiresPermission: android.app.WallpaperInfo#getSettingsSliceUri():
+    
+RequiresPermission: android.app.WallpaperManager#clear():
+    
+RequiresPermission: android.app.WallpaperManager#clearWallpaper():
+    
+RequiresPermission: android.app.WallpaperManager#setBitmap(android.graphics.Bitmap):
+    
+RequiresPermission: android.app.WallpaperManager#setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean):
+    
+RequiresPermission: android.app.WallpaperManager#setDisplayPadding(android.graphics.Rect):
+    
+RequiresPermission: android.app.WallpaperManager#setResource(int):
+    
+RequiresPermission: android.app.WallpaperManager#setStream(java.io.InputStream):
+    
+RequiresPermission: android.app.WallpaperManager#setStream(java.io.InputStream, android.graphics.Rect, boolean):
+    
+RequiresPermission: android.app.WallpaperManager#suggestDesiredDimensions(int, int):
+    
+RequiresPermission: android.app.admin.DevicePolicyManager#bindDeviceAdminServiceAsUser(android.content.ComponentName, android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle):
+    
+RequiresPermission: android.app.admin.DevicePolicyManager#getPasswordComplexity():
+    
+RequiresPermission: android.app.admin.DevicePolicyManager#setAlwaysOnVpnPackage(android.content.ComponentName, String, boolean):
+    
+RequiresPermission: android.app.backup.BackupManager#dataChanged(String):
+    
+RequiresPermission: android.app.usage.StorageStatsManager#queryExternalStatsForUser(java.util.UUID, android.os.UserHandle):
+    
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForPackage(java.util.UUID, String, android.os.UserHandle):
+    
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForUid(java.util.UUID, int):
+    
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForUser(java.util.UUID, android.os.UserHandle):
+    
+RequiresPermission: android.app.usage.UsageStatsManager#queryAndAggregateUsageStats(long, long):
+    
+RequiresPermission: android.app.usage.UsageStatsManager#queryConfigurations(int, long, long):
+    
+RequiresPermission: android.app.usage.UsageStatsManager#queryEventStats(int, long, long):
+    
+RequiresPermission: android.app.usage.UsageStatsManager#queryEvents(long, long):
+    
+RequiresPermission: android.app.usage.UsageStatsManager#queryUsageStats(int, long, long):
+    
+RequiresPermission: android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed(int, android.os.UserHandle, android.content.ComponentName, android.os.Bundle):
+    
+RequiresPermission: android.bluetooth.BluetoothA2dp#isA2dpPlaying(android.bluetooth.BluetoothDevice):
+    
+RequiresPermission: android.bluetooth.BluetoothAdapter#getName():
+    
+RequiresPermission: android.bluetooth.BluetoothDevice#setPin(byte[]):
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#abortReliableWrite():
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#beginReliableWrite():
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#disconnect():
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#discoverServices():
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#executeReliableWrite():
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#getService(java.util.UUID):
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#getServices():
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#readCharacteristic(android.bluetooth.BluetoothGattCharacteristic):
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#readDescriptor(android.bluetooth.BluetoothGattDescriptor):
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#readRemoteRssi():
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#requestMtu(int):
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean):
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic):
+    
+RequiresPermission: android.bluetooth.BluetoothGatt#writeDescriptor(android.bluetooth.BluetoothGattDescriptor):
+    
+RequiresPermission: android.bluetooth.BluetoothGattCharacteristic#BluetoothGattCharacteristic(java.util.UUID, int, int):
+    
+RequiresPermission: android.bluetooth.BluetoothGattCharacteristic#addDescriptor(android.bluetooth.BluetoothGattDescriptor):
+    
+RequiresPermission: android.bluetooth.BluetoothGattDescriptor#BluetoothGattDescriptor(java.util.UUID, int):
+    
+RequiresPermission: android.bluetooth.BluetoothGattServer#addService(android.bluetooth.BluetoothGattService):
+    
+RequiresPermission: android.bluetooth.BluetoothGattServer#cancelConnection(android.bluetooth.BluetoothDevice):
+    
+RequiresPermission: android.bluetooth.BluetoothGattServer#clearServices():
+    
+RequiresPermission: android.bluetooth.BluetoothGattServer#connect(android.bluetooth.BluetoothDevice, boolean):
+    
+RequiresPermission: android.bluetooth.BluetoothGattServer#getService(java.util.UUID):
+    
+RequiresPermission: android.bluetooth.BluetoothGattServer#getServices():
+    
+RequiresPermission: android.bluetooth.BluetoothGattServer#notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean):
+    
+RequiresPermission: android.bluetooth.BluetoothGattServer#removeService(android.bluetooth.BluetoothGattService):
+    
+RequiresPermission: android.bluetooth.BluetoothGattServer#sendResponse(android.bluetooth.BluetoothDevice, int, int, int, byte[]):
+    
+RequiresPermission: android.bluetooth.BluetoothGattService#BluetoothGattService(java.util.UUID, int):
+    
+RequiresPermission: android.bluetooth.BluetoothGattService#addCharacteristic(android.bluetooth.BluetoothGattCharacteristic):
+    
+RequiresPermission: android.bluetooth.BluetoothGattService#addService(android.bluetooth.BluetoothGattService):
+    
+RequiresPermission: android.bluetooth.BluetoothHeadset#isAudioConnected(android.bluetooth.BluetoothDevice):
+    
+RequiresPermission: android.bluetooth.BluetoothHeadset#sendVendorSpecificResultCode(android.bluetooth.BluetoothDevice, String, String):
+    
+RequiresPermission: android.bluetooth.BluetoothHeadset#startVoiceRecognition(android.bluetooth.BluetoothDevice):
+    
+RequiresPermission: android.bluetooth.BluetoothHeadset#stopVoiceRecognition(android.bluetooth.BluetoothDevice):
+    
+RequiresPermission: android.bluetooth.BluetoothHealth#connectChannelToSource(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration):
+    
+RequiresPermission: android.bluetooth.BluetoothHealth#disconnectChannel(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration, int):
+    
+RequiresPermission: android.bluetooth.BluetoothHealth#getConnectedDevices():
+    
+RequiresPermission: android.bluetooth.BluetoothHealth#getConnectionState(android.bluetooth.BluetoothDevice):
+    
+RequiresPermission: android.bluetooth.BluetoothHealth#getDevicesMatchingConnectionStates(int[]):
+    
+RequiresPermission: android.bluetooth.BluetoothHealth#getMainChannelFd(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration):
+    
+RequiresPermission: android.bluetooth.BluetoothHealth#registerSinkAppConfiguration(String, int, android.bluetooth.BluetoothHealthCallback):
+    
+RequiresPermission: android.bluetooth.BluetoothHealth#unregisterAppConfiguration(android.bluetooth.BluetoothHealthAppConfiguration):
+    
+RequiresPermission: android.bluetooth.le.AdvertisingSet#enableAdvertising(boolean, int, int):
+    
+RequiresPermission: android.bluetooth.le.BluetoothLeAdvertiser#startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback):
+    
+RequiresPermission: android.bluetooth.le.BluetoothLeAdvertiser#startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback):
+    
+RequiresPermission: android.bluetooth.le.BluetoothLeAdvertiser#stopAdvertising(android.bluetooth.le.AdvertiseCallback):
+    
+RequiresPermission: android.companion.CompanionDeviceManager#associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler):
+    
+RequiresPermission: android.content.ContentResolver#addPeriodicSync(android.accounts.Account, String, android.os.Bundle, long):
+    
+RequiresPermission: android.content.ContentResolver#cancelSync(android.content.SyncRequest):
+    
+RequiresPermission: android.content.ContentResolver#getCurrentSync():
+    
+RequiresPermission: android.content.ContentResolver#getCurrentSyncs():
+    
+RequiresPermission: android.content.ContentResolver#getIsSyncable(android.accounts.Account, String):
+    
+RequiresPermission: android.content.ContentResolver#getMasterSyncAutomatically():
+    
+RequiresPermission: android.content.ContentResolver#getPeriodicSyncs(android.accounts.Account, String):
+    
+RequiresPermission: android.content.ContentResolver#getSyncAutomatically(android.accounts.Account, String):
+    
+RequiresPermission: android.content.ContentResolver#isSyncActive(android.accounts.Account, String):
+    
+RequiresPermission: android.content.ContentResolver#isSyncPending(android.accounts.Account, String):
+    
+RequiresPermission: android.content.ContentResolver#removePeriodicSync(android.accounts.Account, String, android.os.Bundle):
+    
+RequiresPermission: android.content.ContentResolver#setIsSyncable(android.accounts.Account, String, int):
+    
+RequiresPermission: android.content.ContentResolver#setMasterSyncAutomatically(boolean):
+    
+RequiresPermission: android.content.ContentResolver#setSyncAutomatically(android.accounts.Account, String, boolean):
+    
+RequiresPermission: android.content.Context#clearWallpaper():
+    
+RequiresPermission: android.content.Context#getExternalCacheDir():
+    
+RequiresPermission: android.content.Context#getExternalCacheDirs():
+    
+RequiresPermission: android.content.Context#getExternalFilesDir(String):
+    
+RequiresPermission: android.content.Context#getExternalFilesDirs(String):
+    
+RequiresPermission: android.content.Context#getExternalMediaDirs():
+    
+RequiresPermission: android.content.Context#getObbDir():
+    
+RequiresPermission: android.content.Context#getObbDirs():
+    
+RequiresPermission: android.content.Context#removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle):
+    
+RequiresPermission: android.content.Context#setWallpaper(android.graphics.Bitmap):
+    
+RequiresPermission: android.content.Context#setWallpaper(java.io.InputStream):
+    
+RequiresPermission: android.content.pm.LauncherApps.Callback#onPackagesSuspended(String[], android.os.UserHandle, android.os.Bundle):
+    
+RequiresPermission: android.content.pm.PackageManager#canRequestPackageInstalls():
+    
+RequiresPermission: android.content.pm.PackageManager#getSuspendedPackageAppExtras():
+    
+RequiresPermission: android.content.pm.PackageManager#isPackageSuspended():
+    
+RequiresPermission: android.hardware.camera2.CameraCharacteristics#getKeysNeedingPermission():
+    
+RequiresPermission: android.hardware.usb.UsbManager#hasPermission(android.hardware.usb.UsbDevice):
+    
+RequiresPermission: android.hardware.usb.UsbManager#requestPermission(android.hardware.usb.UsbDevice, android.app.PendingIntent):
+    
+RequiresPermission: android.location.LocationManager#addGpsStatusListener(android.location.GpsStatus.Listener):
+    
+RequiresPermission: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener):
+    
+RequiresPermission: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
+    
+RequiresPermission: android.location.LocationManager#addNmeaListener(java.util.concurrent.Executor, android.location.OnNmeaMessageListener):
+    
+RequiresPermission: android.location.LocationManager#addProximityAlert(double, double, float, long, android.app.PendingIntent):
+    
+RequiresPermission: android.location.LocationManager#registerGnssStatusCallback(android.location.GnssStatus.Callback):
+    
+RequiresPermission: android.location.LocationManager#registerGnssStatusCallback(android.location.GnssStatus.Callback, android.os.Handler):
+    
+RequiresPermission: android.location.LocationManager#registerGnssStatusCallback(java.util.concurrent.Executor, android.location.GnssStatus.Callback):
+    
+RequiresPermission: android.media.AudioManager#startBluetoothSco():
+    
+RequiresPermission: android.media.AudioManager#stopBluetoothSco():
+    
+RequiresPermission: android.media.MediaExtractor#setDataSource(String):
+    
+RequiresPermission: android.media.MediaExtractor#setDataSource(String, java.util.Map<java.lang.String,java.lang.String>):
+    
+RequiresPermission: android.media.MediaExtractor#setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String,java.lang.String>):
+    
+RequiresPermission: android.media.MediaPlayer#setWakeMode(android.content.Context, int):
+    
+RequiresPermission: android.media.MediaSession2Service#onUpdateNotification(android.media.MediaSession2):
+    
+RequiresPermission: android.media.RingtoneManager#getCursor():
+    
+RequiresPermission: android.media.RingtoneManager#getValidRingtoneUri(android.content.Context):
+    
+RequiresPermission: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName):
+    
+RequiresPermission: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler):
+    
+RequiresPermission: android.media.session.MediaSessionManager#getActiveSessions(android.content.ComponentName):
+    
+RequiresPermission: android.media.session.MediaSessionManager#isTrustedForMediaControl(android.media.session.MediaSessionManager.RemoteUserInfo):
+    
+RequiresPermission: android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest, android.app.PendingIntent):
+    
+RequiresPermission: android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback):
+    
+RequiresPermission: android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler):
+    
+RequiresPermission: android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler, int):
+    
+RequiresPermission: android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, int):
+    
+RequiresPermission: android.net.sip.SipAudioCall#setSpeakerMode(boolean):
+    
+RequiresPermission: android.net.sip.SipAudioCall#startAudio():
+    
+RequiresPermission: android.net.wifi.WifiManager#getScanResults():
+    
+RequiresPermission: android.net.wifi.WifiManager#setWifiEnabled(boolean):
+    
+RequiresPermission: android.net.wifi.WifiManager#startLocalOnlyHotspot(android.net.wifi.WifiManager.LocalOnlyHotspotCallback, android.os.Handler):
+    
+RequiresPermission: android.net.wifi.WifiManager#startScan():
+    
+RequiresPermission: android.net.wifi.aware.IdentityChangedListener#onIdentityChanged(byte[]):
+    
+RequiresPermission: android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler):
+    
+RequiresPermission: android.net.wifi.aware.WifiAwareSession#publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler):
+    
+RequiresPermission: android.net.wifi.aware.WifiAwareSession#subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler):
+    
+RequiresPermission: android.nfc.NfcAdapter#disableForegroundDispatch(android.app.Activity):
+    
+RequiresPermission: android.nfc.NfcAdapter#disableForegroundNdefPush(android.app.Activity):
+    
+RequiresPermission: android.nfc.NfcAdapter#enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]):
+    
+RequiresPermission: android.nfc.NfcAdapter#enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage):
+    
+RequiresPermission: android.nfc.NfcAdapter#setBeamPushUris(android.net.Uri[], android.app.Activity):
+    
+RequiresPermission: android.nfc.NfcAdapter#setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity):
+    
+RequiresPermission: android.nfc.NfcAdapter#setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...):
+    
+RequiresPermission: android.nfc.NfcAdapter#setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...):
+    
+RequiresPermission: android.nfc.NfcAdapter#setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...):
+    
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForAid(android.content.ComponentName, String):
+    
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForCategory(android.content.ComponentName, String):
+    
+RequiresPermission: android.nfc.cardemulation.CardEmulation#setOffHostForService(android.content.ComponentName, String):
+    
+RequiresPermission: android.nfc.tech.IsoDep#getTimeout():
+    
+RequiresPermission: android.nfc.tech.IsoDep#setTimeout(int):
+    
+RequiresPermission: android.nfc.tech.IsoDep#transceive(byte[]):
+    
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyA(int, byte[]):
+    
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyB(int, byte[]):
+    
+RequiresPermission: android.nfc.tech.MifareClassic#decrement(int, int):
+    
+RequiresPermission: android.nfc.tech.MifareClassic#getTimeout():
+    
+RequiresPermission: android.nfc.tech.MifareClassic#increment(int, int):
+    
+RequiresPermission: android.nfc.tech.MifareClassic#readBlock(int):
+    
+RequiresPermission: android.nfc.tech.MifareClassic#restore(int):
+    
+RequiresPermission: android.nfc.tech.MifareClassic#setTimeout(int):
+    
+RequiresPermission: android.nfc.tech.MifareClassic#transceive(byte[]):
+    
+RequiresPermission: android.nfc.tech.MifareClassic#transfer(int):
+    
+RequiresPermission: android.nfc.tech.MifareClassic#writeBlock(int, byte[]):
+    
+RequiresPermission: android.nfc.tech.MifareUltralight#getTimeout():
+    
+RequiresPermission: android.nfc.tech.MifareUltralight#readPages(int):
+    
+RequiresPermission: android.nfc.tech.MifareUltralight#setTimeout(int):
+    
+RequiresPermission: android.nfc.tech.MifareUltralight#transceive(byte[]):
+    
+RequiresPermission: android.nfc.tech.MifareUltralight#writePage(int, byte[]):
+    
+RequiresPermission: android.nfc.tech.Ndef#getNdefMessage():
+    
+RequiresPermission: android.nfc.tech.Ndef#isWritable():
+    
+RequiresPermission: android.nfc.tech.Ndef#makeReadOnly():
+    
+RequiresPermission: android.nfc.tech.Ndef#writeNdefMessage(android.nfc.NdefMessage):
+    
+RequiresPermission: android.nfc.tech.NdefFormatable#format(android.nfc.NdefMessage):
+    
+RequiresPermission: android.nfc.tech.NdefFormatable#formatReadOnly(android.nfc.NdefMessage):
+    
+RequiresPermission: android.nfc.tech.NfcA#getTimeout():
+    
+RequiresPermission: android.nfc.tech.NfcA#setTimeout(int):
+    
+RequiresPermission: android.nfc.tech.NfcA#transceive(byte[]):
+    
+RequiresPermission: android.nfc.tech.NfcB#transceive(byte[]):
+    
+RequiresPermission: android.nfc.tech.NfcF#getTimeout():
+    
+RequiresPermission: android.nfc.tech.NfcF#setTimeout(int):
+    
+RequiresPermission: android.nfc.tech.NfcF#transceive(byte[]):
+    
+RequiresPermission: android.nfc.tech.NfcV#transceive(byte[]):
+    
+RequiresPermission: android.nfc.tech.TagTechnology#close():
+    
+RequiresPermission: android.nfc.tech.TagTechnology#connect():
+    
+RequiresPermission: android.os.Build#getSerial():
+    
+RequiresPermission: android.os.Debug#dumpService(String, java.io.FileDescriptor, String[]):
+    
+RequiresPermission: android.os.Environment#getExternalStorageDirectory():
+    
+RequiresPermission: android.os.PowerManager#newWakeLock(int, String):
+    
+RequiresPermission: android.os.PowerManager#reboot(String):
+    
+RequiresPermission: android.os.RecoverySystem#rebootWipeUserData(android.content.Context):
+    
+RequiresPermission: android.os.StrictMode.VmPolicy.Builder#detectFileUriExposure():
+    
+RequiresPermission: android.os.UserManager#getUserName():
+    
+RequiresPermission: android.os.UserManager#isUserUnlocked(android.os.UserHandle):
+    
+RequiresPermission: android.os.health.SystemHealthManager#takeUidSnapshot(int):
+    
+RequiresPermission: android.os.health.SystemHealthManager#takeUidSnapshots(int[]):
+    
+RequiresPermission: android.os.storage.StorageVolume#createAccessIntent(String):
+    
+RequiresPermission: android.provider.MediaStore#setRequireOriginal(android.net.Uri):
+    
+RequiresPermission: android.provider.Settings#canDrawOverlays(android.content.Context):
+    
+RequiresPermission: android.provider.Settings.System#canWrite(android.content.Context):
+    
+RequiresPermission: android.telecom.TelecomManager#acceptHandover(android.net.Uri, int, android.telecom.PhoneAccountHandle):
+    
+RequiresPermission: android.telecom.TelecomManager#acceptRingingCall():
+    
+RequiresPermission: android.telecom.TelecomManager#acceptRingingCall(int):
+    
+RequiresPermission: android.telecom.TelecomManager#addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle):
+    
+RequiresPermission: android.telecom.TelecomManager#cancelMissedCallsNotification():
+    
+RequiresPermission: android.telecom.TelecomManager#endCall():
+    
+RequiresPermission: android.telecom.TelecomManager#getAdnUriForPhoneAccount(android.telecom.PhoneAccountHandle):
+    
+RequiresPermission: android.telecom.TelecomManager#getCallCapablePhoneAccounts():
+    
+RequiresPermission: android.telecom.TelecomManager#getDefaultOutgoingPhoneAccount(String):
+    
+RequiresPermission: android.telecom.TelecomManager#getLine1Number(android.telecom.PhoneAccountHandle):
+    
+RequiresPermission: android.telecom.TelecomManager#getSelfManagedPhoneAccounts():
+    
+RequiresPermission: android.telecom.TelecomManager#getVoiceMailNumber(android.telecom.PhoneAccountHandle):
+    
+RequiresPermission: android.telecom.TelecomManager#handleMmi(String):
+    
+RequiresPermission: android.telecom.TelecomManager#handleMmi(String, android.telecom.PhoneAccountHandle):
+    
+RequiresPermission: android.telecom.TelecomManager#isInCall():
+    
+RequiresPermission: android.telecom.TelecomManager#isInManagedCall():
+    
+RequiresPermission: android.telecom.TelecomManager#isVoiceMailNumber(android.telecom.PhoneAccountHandle, String):
+    
+RequiresPermission: android.telecom.TelecomManager#placeCall(android.net.Uri, android.os.Bundle):
+    
+RequiresPermission: android.telecom.TelecomManager#showInCallScreen(boolean):
+    
+RequiresPermission: android.telecom.TelecomManager#silenceRinger():
+    
+RequiresPermission: android.telephony.CarrierConfigManager#getConfig():
+    
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigByComponentForSubId(String, int):
+    
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigForSubId(int):
+    
+RequiresPermission: android.telephony.PhoneStateListener#onCallStateChanged(int, String):
+    
+RequiresPermission: android.telephony.SmsManager#injectSmsPdu(byte[], String, android.app.PendingIntent):
+    
+RequiresPermission: android.telephony.SmsManager#sendDataMessage(String, String, short, byte[], android.app.PendingIntent, android.app.PendingIntent):
+    
+RequiresPermission: android.telephony.SmsManager#sendMultipartTextMessage(String, String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>):
+    
+RequiresPermission: android.telephony.SmsManager#sendTextMessage(String, String, String, android.app.PendingIntent, android.app.PendingIntent):
+    
+RequiresPermission: android.telephony.SmsManager#sendTextMessageWithoutPersisting(String, String, String, android.app.PendingIntent, android.app.PendingIntent):
+    
+RequiresPermission: android.telephony.SubscriptionManager#addSubscriptionsIntoGroup(java.util.List<java.lang.Integer>, android.os.ParcelUuid):
+    
+RequiresPermission: android.telephony.SubscriptionManager#createSubscriptionGroup(java.util.List<java.lang.Integer>):
+    
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfo(int):
+    
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfoCount():
+    
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfoForSimSlotIndex(int):
+    
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfoList():
+    
+RequiresPermission: android.telephony.SubscriptionManager#getOpportunisticSubscriptions():
+    
+RequiresPermission: android.telephony.SubscriptionManager#getSubscriptionsInGroup(android.os.ParcelUuid):
+    
+RequiresPermission: android.telephony.SubscriptionManager#removeSubscriptionsFromGroup(java.util.List<java.lang.Integer>, android.os.ParcelUuid):
+    
+RequiresPermission: android.telephony.SubscriptionManager#setOpportunistic(boolean, int):
+    
+RequiresPermission: android.telephony.TelephonyManager#doesSwitchMultiSimConfigTriggerReboot():
+    
+RequiresPermission: android.telephony.TelephonyManager#getCarrierConfig():
+    
+RequiresPermission: android.telephony.TelephonyManager#getDataNetworkType():
+    
+RequiresPermission: android.telephony.TelephonyManager#getDeviceId():
+    
+RequiresPermission: android.telephony.TelephonyManager#getDeviceId(int):
+    
+RequiresPermission: android.telephony.TelephonyManager#getDeviceSoftwareVersion():
+    
+RequiresPermission: android.telephony.TelephonyManager#getEmergencyNumberList():
+    
+RequiresPermission: android.telephony.TelephonyManager#getEmergencyNumberList(int):
+    
+RequiresPermission: android.telephony.TelephonyManager#getForbiddenPlmns():
+    
+RequiresPermission: android.telephony.TelephonyManager#getGroupIdLevel1():
+    
+RequiresPermission: android.telephony.TelephonyManager#getImei(int):
+    
+RequiresPermission: android.telephony.TelephonyManager#getLine1Number():
+    
+RequiresPermission: android.telephony.TelephonyManager#getMeid():
+    
+RequiresPermission: android.telephony.TelephonyManager#getMeid(int):
+    
+RequiresPermission: android.telephony.TelephonyManager#getNai():
+    
+RequiresPermission: android.telephony.TelephonyManager#getPreferredOpportunisticDataSubscription():
+    
+RequiresPermission: android.telephony.TelephonyManager#getServiceState():
+    
+RequiresPermission: android.telephony.TelephonyManager#getSimSerialNumber():
+    
+RequiresPermission: android.telephony.TelephonyManager#getSubscriberId():
+    
+RequiresPermission: android.telephony.TelephonyManager#getVisualVoicemailPackageName():
+    
+RequiresPermission: android.telephony.TelephonyManager#getVoiceMailAlphaTag():
+    
+RequiresPermission: android.telephony.TelephonyManager#getVoiceMailNumber():
+    
+RequiresPermission: android.telephony.TelephonyManager#getVoiceNetworkType():
+    
+RequiresPermission: android.telephony.TelephonyManager#iccCloseLogicalChannel(int):
+    
+RequiresPermission: android.telephony.TelephonyManager#iccExchangeSimIO(int, int, int, int, int, String):
+    
+RequiresPermission: android.telephony.TelephonyManager#iccOpenLogicalChannel(String):
+    
+RequiresPermission: android.telephony.TelephonyManager#iccOpenLogicalChannel(String, int):
+    
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduBasicChannel(int, int, int, int, int, String):
+    
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduLogicalChannel(int, int, int, int, int, int, String):
+    
+RequiresPermission: android.telephony.TelephonyManager#isDataEnabled():
+    
+RequiresPermission: android.telephony.TelephonyManager#isDataRoamingEnabled():
+    
+RequiresPermission: android.telephony.TelephonyManager#isMultiSimSupported():
+    
+RequiresPermission: android.telephony.TelephonyManager#requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback):
+    
+RequiresPermission: android.telephony.TelephonyManager#sendEnvelopeWithStatus(String):
+    
+RequiresPermission: android.telephony.TelephonyManager#sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler):
+    
+RequiresPermission: android.telephony.TelephonyManager#sendVisualVoicemailSms(String, int, String, android.app.PendingIntent):
+    
+RequiresPermission: android.telephony.TelephonyManager#setDataEnabled(boolean):
+    
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeAutomatic():
+    
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeManual(String, boolean):
+    
+RequiresPermission: android.telephony.TelephonyManager#setPreferredOpportunisticDataSubscription(int, boolean, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    
+RequiresPermission: android.telephony.TelephonyManager#setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri):
+    
+RequiresPermission: android.telephony.TelephonyManager#setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean):
+    
+RequiresPermission: android.telephony.TelephonyManager#switchMultiSimConfig(int):
+    
+RequiresPermission: android.telephony.TelephonyManager#updateAvailableNetworks(java.util.List<android.telephony.AvailableNetworkInfo>, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    
+RequiresPermission: android.telephony.euicc.EuiccManager#deleteSubscription(int, android.app.PendingIntent):
+    
+RequiresPermission: android.telephony.euicc.EuiccManager#downloadSubscription(android.telephony.euicc.DownloadableSubscription, boolean, android.app.PendingIntent):
+    
+RequiresPermission: android.telephony.euicc.EuiccManager#switchToSubscription(int, android.app.PendingIntent):
+    
+RequiresPermission: android.telephony.euicc.EuiccManager#updateSubscriptionNickname(int, String, android.app.PendingIntent):
+    
+RequiresPermission: android.view.inputmethod.InputMethodManager#setCurrentInputMethodSubtype(android.view.inputmethod.InputMethodSubtype):
+    
+RequiresPermission: android.view.inputmethod.InputMethodManager#setInputMethod(android.os.IBinder, String):
+    
+RequiresPermission: android.view.inputmethod.InputMethodManager#setInputMethodAndSubtype(android.os.IBinder, String, android.view.inputmethod.InputMethodSubtype):
+    
+RequiresPermission: android.webkit.WebSettings#setBlockNetworkLoads(boolean):
+    
+RequiresPermission: android.webkit.WebSettings#setGeolocationEnabled(boolean):
+    
+
+
+SamShouldBeLast: android.location.LocationManager#registerGnssMeasurementsCallback(java.util.concurrent.Executor, android.location.GnssMeasurementsEvent.Callback):
+    
+SamShouldBeLast: android.location.LocationManager#registerGnssNavigationMessageCallback(java.util.concurrent.Executor, android.location.GnssNavigationMessage.Callback):
+    
+SamShouldBeLast: android.location.LocationManager#registerGnssStatusCallback(java.util.concurrent.Executor, android.location.GnssStatus.Callback):
+    
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, java.util.concurrent.Executor, android.location.LocationListener):
+    
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, java.util.concurrent.Executor, android.location.LocationListener):
+    
+
+
+StreamFiles: android.content.res.loader.DirectoryResourceLoader#DirectoryResourceLoader(java.io.File):
+    Methods accepting `File` should also accept `FileDescriptor` or streams: constructor android.content.res.loader.DirectoryResourceLoader(java.io.File)
+
+
+Todo: android.hardware.camera2.params.StreamConfigurationMap:
+    
+Todo: android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration(Class<T>, android.util.Size):
+    
+Todo: android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration(int, android.util.Size):
+    
+Todo: android.provider.ContactsContract.RawContacts#newEntityIterator(android.database.Cursor):
+    
+Todo: android.telephony.CarrierConfigManager#KEY_USE_OTASP_FOR_PROVISIONING_BOOL:
+    
diff --git a/api/system-current.txt b/api/system-current.txt
index 9231536..c6b6fff 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -172,6 +172,7 @@
     field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
     field public static final String REQUEST_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final String RESET_PASSWORD = "android.permission.RESET_PASSWORD";
+    field public static final String RESTORE_RUNTIME_PERMISSIONS = "android.permission.RESTORE_RUNTIME_PERMISSIONS";
     field public static final String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
     field public static final String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
     field public static final String REVIEW_ACCESSIBILITY_SERVICES = "android.permission.REVIEW_ACCESSIBILITY_SERVICES";
@@ -457,6 +458,7 @@
   public static final class AppOpsManager.OpEntry implements android.os.Parcelable {
     method public int describeContents();
     method public long getDuration();
+    method @NonNull public java.util.Map<java.lang.String,android.app.AppOpsManager.OpFeatureEntry> getFeatures();
     method public long getLastAccessBackgroundTime(int);
     method public long getLastAccessForegroundTime(int);
     method public long getLastAccessTime(int);
@@ -470,13 +472,35 @@
     method public long getLastRejectTime(int, int, int);
     method public int getMode();
     method @NonNull public String getOpStr();
+    method @Deprecated @Nullable public String getProxyPackageName();
+    method @Nullable public String getProxyPackageName(int, int);
+    method @Deprecated public int getProxyUid();
+    method public int getProxyUid(int, int);
+    method public boolean isRunning();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
+  }
+
+  public static final class AppOpsManager.OpFeatureEntry {
+    method public long getDuration();
+    method public long getLastAccessBackgroundTime(int);
+    method public long getLastAccessForegroundTime(int);
+    method public long getLastAccessTime(int);
+    method public long getLastAccessTime(int, int, int);
+    method public long getLastBackgroundDuration(int);
+    method public long getLastDuration(int, int, int);
+    method public long getLastForegroundDuration(int);
+    method public long getLastRejectBackgroundTime(int);
+    method public long getLastRejectForegroundTime(int);
+    method public long getLastRejectTime(int);
+    method public long getLastRejectTime(int, int, int);
+    method @Nullable public String getProxyFeatureId();
+    method @Nullable public String getProxyFeatureId(int, int);
     method @Nullable public String getProxyPackageName();
     method @Nullable public String getProxyPackageName(int, int);
     method public int getProxyUid();
     method public int getProxyUid(int, int);
     method public boolean isRunning();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
   }
 
   public static final class AppOpsManager.PackageOps implements android.os.Parcelable {
@@ -1359,7 +1383,7 @@
 
   public abstract class Context {
     method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public boolean bindServiceAsUser(@RequiresPermission android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle);
-    method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle);
+    method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle, int);
     method public abstract android.content.Context createCredentialProtectedStorageContext();
     method @NonNull public android.content.Context createPackageContextAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Nullable public abstract java.io.File getPreloadsFileCache();
@@ -1754,7 +1778,9 @@
     field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000
     field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
     field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
+    field public static final int PROTECTION_FLAG_TELEPHONY = 4194304; // 0x400000
     field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000
+    field public static final int PROTECTION_FLAG_WIFI = 8388608; // 0x800000
     field @Nullable public final String backgroundPermission;
     field @StringRes public int requestRes;
   }
@@ -3427,6 +3453,7 @@
 
   public class LocationManager {
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
     method @Nullable public String getExtraLocationControllerPackage();
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int getGnssBatchSize();
     method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GnssCapabilities getGnssCapabilities();
@@ -5207,6 +5234,7 @@
     field public static final String ACTION_UPDATE_CARRIER_PROVISIONING_URLS = "android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS";
     field public static final String ACTION_UPDATE_CONVERSATION_ACTIONS = "android.intent.action.UPDATE_CONVERSATION_ACTIONS";
     field public static final String ACTION_UPDATE_CT_LOGS = "android.intent.action.UPDATE_CT_LOGS";
+    field public static final String ACTION_UPDATE_EMERGENCY_NUMBER_DB = "android.os.action.UPDATE_EMERGENCY_NUMBER_DB";
     field public static final String ACTION_UPDATE_INTENT_FIREWALL = "android.intent.action.UPDATE_INTENT_FIREWALL";
     field public static final String ACTION_UPDATE_LANG_ID = "android.intent.action.UPDATE_LANG_ID";
     field public static final String ACTION_UPDATE_NETWORK_WATCHLIST = "android.intent.action.UPDATE_NETWORK_WATCHLIST";
@@ -5688,18 +5716,13 @@
 
 }
 
-package android.os.telephony {
-
-  public class TelephonyRegistryManager {
-    method public void notifyCarrierNetworkChange(boolean);
-  }
-
-}
-
 package android.permission {
 
   public final class PermissionControllerManager {
+    method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.RESTORE_RUNTIME_PERMISSIONS}) public void applyStagedRuntimePermissionBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+    method @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public void getRuntimePermissionBackup(@NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<byte[]>);
     method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull java.util.concurrent.Executor, @NonNull android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.RESTORE_RUNTIME_PERMISSIONS}) public void stageAndApplyRuntimePermissionsBackup(@NonNull byte[], @NonNull android.os.UserHandle);
     field public static final int COUNT_ONLY_WHEN_GRANTED = 1; // 0x1
     field public static final int COUNT_WHEN_SYSTEM = 2; // 0x2
     field public static final int REASON_INSTALLER_POLICY_VIOLATION = 2; // 0x2
@@ -5713,17 +5736,19 @@
 
   public abstract class PermissionControllerService extends android.app.Service {
     ctor public PermissionControllerService();
+    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);
     method @BinderThread public abstract void onGetAppPermissions(@NonNull String, @NonNull java.util.function.Consumer<java.util.List<android.permission.RuntimePermissionPresentationInfo>>);
     method @BinderThread public abstract void onGetPermissionUsages(boolean, long, @NonNull java.util.function.Consumer<java.util.List<android.permission.RuntimePermissionUsageInfo>>);
     method @BinderThread public abstract void onGetRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.OutputStream, @NonNull Runnable);
     method @BinderThread public abstract void onGrantOrUpgradeDefaultRuntimePermissions(@NonNull Runnable);
-    method @BinderThread public abstract void onRestoreDelayedRuntimePermissionsBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.function.Consumer<java.lang.Boolean>);
-    method @BinderThread public abstract void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
+    method @Deprecated @BinderThread public void onRestoreDelayedRuntimePermissionsBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+    method @Deprecated @BinderThread public void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
     method @BinderThread public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String, @NonNull Runnable);
     method @BinderThread public abstract void onRevokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull String, @NonNull java.util.function.Consumer<java.util.Map<java.lang.String,java.util.List<java.lang.String>>>);
     method @BinderThread public abstract void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull String, @NonNull String, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+    method @BinderThread public void onStageAndApplyRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
     method @BinderThread public void onUpdateUserSensitive();
     field public static final String SERVICE_INTERFACE = "android.permission.PermissionControllerService";
   }
@@ -6999,7 +7024,26 @@
 
   public abstract class Connection extends android.telecom.Conferenceable {
     method @Deprecated public final android.telecom.AudioState getAudioState();
+    method public final int getCallRadioTech();
+    method public final long getConnectElapsedTimeMillis();
+    method public final long getConnectTimeMillis();
+    method @Nullable public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
+    method @Nullable public final String getTelecomCallId();
     method @Deprecated public void onAudioStateChanged(android.telecom.AudioState);
+    method public final void resetConnectionTime();
+    method public void setCallDirection(int);
+    method public final void setCallRadioTech(int);
+    method public final void setConnectTimeMillis(long);
+    method public final void setConnectionStartElapsedRealTime(long);
+    method public void setPhoneAccountHandle(@NonNull android.telecom.PhoneAccountHandle);
+    method public void setTelecomCallId(@NonNull String);
+    field public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 2097152; // 0x200000
+    field public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 262144; // 0x40000
+    field public static final String EXTRA_DISABLE_ADD_CALL = "android.telecom.extra.DISABLE_ADD_CALL";
+    field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 1; // 0x1
+    field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
+    field public static final int PROPERTY_IS_DOWNGRADED_CONFERENCE = 64; // 0x40
+    field public static final int PROPERTY_REMOTELY_HOSTED = 2048; // 0x800
   }
 
   public abstract class InCallService extends android.app.Service {
@@ -7314,7 +7358,7 @@
   public abstract class CellBroadcastService extends android.app.Service {
     ctor public CellBroadcastService();
     method @CallSuper public android.os.IBinder onBind(android.content.Intent);
-    method public abstract void onCdmaCellBroadcastSms(int, byte[]);
+    method public abstract void onCdmaCellBroadcastSms(int, byte[], int);
     method public abstract void onGsmCellBroadcastSms(int, byte[]);
     field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService";
   }
@@ -8371,6 +8415,14 @@
     field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0
   }
 
+  public class TelephonyRegistryManager {
+    method public void addOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor);
+    method public void addOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor);
+    method public void notifyCarrierNetworkChange(boolean);
+    method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
+    method public void removeOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+  }
+
   public final class UiccAccessRule implements android.os.Parcelable {
     ctor public UiccAccessRule(byte[], @Nullable String, long);
     method public int describeContents();
@@ -9760,9 +9812,10 @@
     method public final long getUserActivityTimeout();
     method public final void setUserActivityTimeout(long);
     field @RequiresPermission(android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS) public static final int SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 524288; // 0x80000
+    field @RequiresPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW) public static final int SYSTEM_FLAG_SHOW_FOR_ALL_USERS = 16; // 0x10
   }
 
-  @IntDef(flag=true, prefix={"SYSTEM_FLAG_"}, value={android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface WindowManager.LayoutParams.SystemFlags {
+  @IntDef(flag=true, prefix={"SYSTEM_FLAG_"}, value={android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface WindowManager.LayoutParams.SystemFlags {
   }
 
 }
diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt
new file mode 100644
index 0000000..57a853a
--- /dev/null
+++ b/api/system-lint-baseline.txt
@@ -0,0 +1,391 @@
+// Baseline format: 1.0
+ActionValue: android.location.Location#EXTRA_NO_GPS_LOCATION:
+    
+
+
+ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions():
+    
+
+
+GenericException: android.app.prediction.AppPredictor#finalize():
+    
+GenericException: android.hardware.location.ContextHubClient#finalize():
+    
+GenericException: android.net.IpSecManager.IpSecTunnelInterface#finalize():
+    
+GenericException: android.service.autofill.augmented.FillWindow#finalize():
+    
+
+
+InterfaceConstant: android.service.storage.ExternalStorageService#SERVICE_INTERFACE:
+    
+
+
+KotlinKeyword: android.app.Notification#when:
+    
+
+
+MissingNullability: android.hardware.soundtrigger.SoundTrigger.ModuleProperties#toString():
+    
+MissingNullability: android.hardware.soundtrigger.SoundTrigger.ModuleProperties#writeToParcel(android.os.Parcel, int) parameter #0:
+    
+MissingNullability: android.media.session.MediaSessionManager.Callback#onAddressedPlayerChanged(android.content.ComponentName) parameter #0:
+    
+MissingNullability: android.media.session.MediaSessionManager.Callback#onAddressedPlayerChanged(android.media.session.MediaSession.Token) parameter #0:
+    
+MissingNullability: android.media.session.MediaSessionManager.Callback#onMediaKeyEventDispatched(android.view.KeyEvent, android.content.ComponentName) parameter #0:
+    
+MissingNullability: android.media.session.MediaSessionManager.Callback#onMediaKeyEventDispatched(android.view.KeyEvent, android.content.ComponentName) parameter #1:
+    
+MissingNullability: android.media.session.MediaSessionManager.Callback#onMediaKeyEventDispatched(android.view.KeyEvent, android.media.session.MediaSession.Token) parameter #0:
+    
+MissingNullability: android.media.session.MediaSessionManager.Callback#onMediaKeyEventDispatched(android.view.KeyEvent, android.media.session.MediaSession.Token) parameter #1:
+    
+MissingNullability: android.media.soundtrigger.SoundTriggerDetectionService#onUnbind(android.content.Intent) parameter #0:
+    
+MissingNullability: android.media.tv.TvRecordingClient.RecordingCallback#onEvent(String, String, android.os.Bundle) parameter #0:
+    
+MissingNullability: android.media.tv.TvRecordingClient.RecordingCallback#onEvent(String, String, android.os.Bundle) parameter #1:
+    
+MissingNullability: android.media.tv.TvRecordingClient.RecordingCallback#onEvent(String, String, android.os.Bundle) parameter #2:
+    
+MissingNullability: android.net.wifi.rtt.RangingRequest.Builder#addResponder(android.net.wifi.rtt.ResponderConfig):
+    
+MissingNullability: android.printservice.recommendation.RecommendationService#attachBaseContext(android.content.Context) parameter #0:
+    
+MissingNullability: android.provider.ContactsContract.MetadataSync#CONTENT_URI:
+    
+MissingNullability: android.provider.ContactsContract.MetadataSync#METADATA_AUTHORITY_URI:
+    
+MissingNullability: android.provider.ContactsContract.MetadataSyncState#CONTENT_URI:
+    
+MissingNullability: android.provider.SearchIndexablesProvider#attachInfo(android.content.Context, android.content.pm.ProviderInfo) parameter #0:
+    
+MissingNullability: android.provider.SearchIndexablesProvider#attachInfo(android.content.Context, android.content.pm.ProviderInfo) parameter #1:
+    
+MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#onUnbind(android.content.Intent) parameter #0:
+    
+MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0:
+    
+MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #1:
+    
+MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #2:
+    
+MissingNullability: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context) parameter #0:
+    
+MissingNullability: android.telecom.CallScreeningService.CallResponse.Builder#setShouldScreenCallFurther(boolean):
+    
+MissingNullability: android.telephony.CallerInfo#toString():
+    
+MissingNullability: android.telephony.CellBroadcastService#onBind(android.content.Intent):
+    
+MissingNullability: android.telephony.CellBroadcastService#onBind(android.content.Intent) parameter #0:
+    
+MissingNullability: android.telephony.CellBroadcastService#onCdmaCellBroadcastSms(int, byte[]) parameter #1:
+    
+MissingNullability: android.telephony.CellBroadcastService#onCdmaCellBroadcastSms(int, byte[], int) parameter #1:
+    
+MissingNullability: android.telephony.CellBroadcastService#onGsmCellBroadcastSms(int, byte[]) parameter #1:
+    
+MissingNullability: android.telephony.ModemActivityInfo#toString():
+    
+MissingNullability: android.telephony.ModemActivityInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+    
+MissingNullability: android.telephony.ModemActivityInfo.TransmitPower#toString():
+    
+MissingNullability: android.telephony.NetworkService#onUnbind(android.content.Intent) parameter #0:
+    
+MissingNullability: android.telephony.SmsCbCmasInfo#toString():
+    
+MissingNullability: android.telephony.SmsCbCmasInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+    
+MissingNullability: android.telephony.SmsCbEtwsInfo#toString():
+    
+MissingNullability: android.telephony.SmsCbEtwsInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+    
+MissingNullability: android.telephony.SmsCbLocation#equals(Object) parameter #0:
+    
+MissingNullability: android.telephony.SmsCbLocation#toString():
+    
+MissingNullability: android.telephony.SmsCbLocation#writeToParcel(android.os.Parcel, int) parameter #0:
+    
+MissingNullability: android.telephony.SmsCbMessage#toString():
+    
+MissingNullability: android.telephony.SmsCbMessage#writeToParcel(android.os.Parcel, int) parameter #0:
+    
+MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringDaily(java.time.ZonedDateTime) parameter #0:
+    
+MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringMonthly(java.time.ZonedDateTime) parameter #0:
+    
+MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringWeekly(java.time.ZonedDateTime) parameter #0:
+    
+MissingNullability: android.telephony.cdma.CdmaSmsCbProgramData#toString():
+    
+MissingNullability: android.telephony.cdma.CdmaSmsCbProgramData#writeToParcel(android.os.Parcel, int) parameter #0:
+    
+MissingNullability: android.telephony.data.DataService#onUnbind(android.content.Intent) parameter #0:
+    
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #1:
+    
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #2:
+    
+MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String):
+    
+MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String) parameter #0:
+    
+
+
+NoClone: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0:
+    
+
+
+ProtectedMember: android.printservice.recommendation.RecommendationService#attachBaseContext(android.content.Context):
+    
+ProtectedMember: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]):
+    
+ProtectedMember: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context):
+    
+
+
+SamShouldBeLast: android.accounts.AccountManager#addAccount(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean):
+    
+SamShouldBeLast: android.accounts.AccountManager#addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, String[]):
+    
+SamShouldBeLast: android.accounts.AccountManager#confirmCredentials(android.accounts.Account, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#editProperties(String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#getAccountsByTypeAndFeatures(String, String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#getAuthToken(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#getAuthToken(android.accounts.Account, String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#getAuthToken(android.accounts.Account, String, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#getAuthTokenByFeatures(String, String, String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#hasFeatures(android.accounts.Account, String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#isCredentialsUpdateSuggested(android.accounts.Account, String, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#renameAccount(android.accounts.Account, String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#startAddAccountSession(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#startUpdateCredentialsSession(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
+    
+SamShouldBeLast: android.accounts.AccountManager#updateCredentials(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
+    
+SamShouldBeLast: android.app.AlarmManager#set(int, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler):
+    
+SamShouldBeLast: android.app.AlarmManager#setExact(int, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler):
+    
+SamShouldBeLast: android.app.AlarmManager#setWindow(int, long, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler):
+    
+SamShouldBeLast: android.app.WallpaperInfo#dump(android.util.Printer, String):
+    
+SamShouldBeLast: android.app.admin.DevicePolicyManager#installSystemUpdate(android.content.ComponentName, android.net.Uri, java.util.concurrent.Executor, android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback):
+    
+SamShouldBeLast: android.content.Context#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection):
+    
+SamShouldBeLast: android.content.Context#bindService(android.content.Intent, int, java.util.concurrent.Executor, android.content.ServiceConnection):
+    
+SamShouldBeLast: android.content.ContextWrapper#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection):
+    
+SamShouldBeLast: android.content.ContextWrapper#bindService(android.content.Intent, int, java.util.concurrent.Executor, android.content.ServiceConnection):
+    
+SamShouldBeLast: android.content.IntentFilter#dump(android.util.Printer, String):
+    
+SamShouldBeLast: android.content.pm.ApplicationInfo#dump(android.util.Printer, String):
+    
+SamShouldBeLast: android.content.pm.LauncherApps#registerPackageInstallerSessionCallback(java.util.concurrent.Executor, android.content.pm.PackageInstaller.SessionCallback):
+    
+SamShouldBeLast: android.content.pm.PackageItemInfo#dumpBack(android.util.Printer, String):
+    
+SamShouldBeLast: android.content.pm.PackageItemInfo#dumpFront(android.util.Printer, String):
+    
+SamShouldBeLast: android.content.pm.ResolveInfo#dump(android.util.Printer, String):
+    
+SamShouldBeLast: android.location.Location#dump(android.util.Printer, String):
+    
+SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
+    
+SamShouldBeLast: android.location.LocationManager#registerGnssMeasurementsCallback(java.util.concurrent.Executor, android.location.GnssMeasurementsEvent.Callback):
+    
+SamShouldBeLast: android.location.LocationManager#registerGnssNavigationMessageCallback(java.util.concurrent.Executor, android.location.GnssNavigationMessage.Callback):
+    
+SamShouldBeLast: android.location.LocationManager#registerGnssStatusCallback(java.util.concurrent.Executor, android.location.GnssStatus.Callback):
+    
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, java.util.concurrent.Executor, android.location.LocationListener):
+    
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, java.util.concurrent.Executor, android.location.LocationListener):
+    
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, java.util.concurrent.Executor, android.location.LocationListener):
+    
+SamShouldBeLast: android.media.AudioFocusRequest.Builder#setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler):
+    
+SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int):
+    
+SamShouldBeLast: android.media.AudioRecord#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
+    
+SamShouldBeLast: android.media.AudioRecord#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback):
+    
+SamShouldBeLast: android.media.AudioRecordingMonitor#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback):
+    
+SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
+    
+SamShouldBeLast: android.media.MediaRecorder#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
+    
+SamShouldBeLast: android.media.MediaRecorder#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback):
+    
+SamShouldBeLast: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName):
+    
+SamShouldBeLast: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler):
+    
+SamShouldBeLast: android.media.session.MediaSessionManager#addOnSession2TokensChangedListener(android.media.session.MediaSessionManager.OnSession2TokensChangedListener, android.os.Handler):
+    
+SamShouldBeLast: android.media.session.MediaSessionManager#registerCallback(java.util.concurrent.Executor, android.media.session.MediaSessionManager.Callback):
+    
+SamShouldBeLast: android.net.ConnectivityManager#createSocketKeepalive(android.net.Network, android.net.IpSecManager.UdpEncapsulationSocket, java.net.InetAddress, java.net.InetAddress, java.util.concurrent.Executor, android.net.SocketKeepalive.Callback):
+    
+SamShouldBeLast: android.net.wifi.rtt.WifiRttManager#startRanging(android.net.wifi.rtt.RangingRequest, java.util.concurrent.Executor, android.net.wifi.rtt.RangingResultCallback):
+    
+SamShouldBeLast: android.nfc.NfcAdapter#enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle):
+    
+SamShouldBeLast: android.nfc.NfcAdapter#ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler):
+    
+SamShouldBeLast: android.nfc.NfcAdapter#setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity):
+    
+SamShouldBeLast: android.nfc.NfcAdapter#setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...):
+    
+SamShouldBeLast: android.nfc.NfcAdapter#setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...):
+    
+SamShouldBeLast: android.os.Binder#attachInterface(android.os.IInterface, String):
+    
+SamShouldBeLast: android.os.Binder#linkToDeath(android.os.IBinder.DeathRecipient, int):
+    
+SamShouldBeLast: android.os.Binder#unlinkToDeath(android.os.IBinder.DeathRecipient, int):
+    
+SamShouldBeLast: android.os.Handler#dump(android.util.Printer, String):
+    
+SamShouldBeLast: android.os.Handler#postAtTime(Runnable, Object, long):
+    
+SamShouldBeLast: android.os.Handler#postAtTime(Runnable, long):
+    
+SamShouldBeLast: android.os.Handler#postDelayed(Runnable, Object, long):
+    
+SamShouldBeLast: android.os.Handler#postDelayed(Runnable, long):
+    
+SamShouldBeLast: android.os.Handler#removeCallbacks(Runnable, Object):
+    
+SamShouldBeLast: android.os.IBinder#linkToDeath(android.os.IBinder.DeathRecipient, int):
+    
+SamShouldBeLast: android.os.IBinder#unlinkToDeath(android.os.IBinder.DeathRecipient, int):
+    
+SamShouldBeLast: android.os.RecoverySystem#verifyPackage(java.io.File, android.os.RecoverySystem.ProgressListener, java.io.File):
+    
+SamShouldBeLast: android.telephony.MbmsDownloadSession#addProgressListener(android.telephony.mbms.DownloadRequest, java.util.concurrent.Executor, android.telephony.mbms.DownloadProgressListener):
+    
+SamShouldBeLast: android.telephony.MbmsDownloadSession#addStatusListener(android.telephony.mbms.DownloadRequest, java.util.concurrent.Executor, android.telephony.mbms.DownloadStatusListener):
+    
+SamShouldBeLast: android.telephony.MbmsDownloadSession#create(android.content.Context, java.util.concurrent.Executor, android.telephony.mbms.MbmsDownloadSessionCallback):
+    
+SamShouldBeLast: android.telephony.MbmsDownloadSession#create(android.content.Context, java.util.concurrent.Executor, int, android.telephony.mbms.MbmsDownloadSessionCallback):
+    
+SamShouldBeLast: android.telephony.MbmsGroupCallSession#create(android.content.Context, int, java.util.concurrent.Executor, android.telephony.mbms.MbmsGroupCallSessionCallback):
+    
+SamShouldBeLast: android.telephony.MbmsGroupCallSession#create(android.content.Context, java.util.concurrent.Executor, android.telephony.mbms.MbmsGroupCallSessionCallback):
+    
+SamShouldBeLast: android.telephony.MbmsGroupCallSession#startGroupCall(long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>, java.util.concurrent.Executor, android.telephony.mbms.GroupCallCallback):
+    
+SamShouldBeLast: android.telephony.MbmsStreamingSession#create(android.content.Context, java.util.concurrent.Executor, android.telephony.mbms.MbmsStreamingSessionCallback):
+    
+SamShouldBeLast: android.telephony.MbmsStreamingSession#create(android.content.Context, java.util.concurrent.Executor, int, android.telephony.mbms.MbmsStreamingSessionCallback):
+    
+SamShouldBeLast: android.telephony.MbmsStreamingSession#startStreaming(android.telephony.mbms.StreamingServiceInfo, java.util.concurrent.Executor, android.telephony.mbms.StreamingServiceCallback):
+    
+SamShouldBeLast: android.telephony.SmsManager#getSmsMessagesForFinancialApp(android.os.Bundle, java.util.concurrent.Executor, android.telephony.SmsManager.FinancialSmsCallback):
+    
+SamShouldBeLast: android.telephony.SubscriptionManager#addOnOpportunisticSubscriptionsChangedListener(java.util.concurrent.Executor, android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener):
+    
+SamShouldBeLast: android.telephony.TelephonyManager#requestCellInfoUpdate(java.util.concurrent.Executor, android.telephony.TelephonyManager.CellInfoCallback):
+    
+SamShouldBeLast: android.telephony.TelephonyManager#requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback):
+    
+SamShouldBeLast: android.telephony.TelephonyManager#setPreferredOpportunisticDataSubscription(int, boolean, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    
+SamShouldBeLast: android.telephony.TelephonyManager#updateAvailableNetworks(java.util.List<android.telephony.AvailableNetworkInfo>, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    
+SamShouldBeLast: android.view.View#postDelayed(Runnable, long):
+    
+SamShouldBeLast: android.view.View#postOnAnimationDelayed(Runnable, long):
+    
+SamShouldBeLast: android.view.View#scheduleDrawable(android.graphics.drawable.Drawable, Runnable, long):
+    
+SamShouldBeLast: android.view.Window#addOnFrameMetricsAvailableListener(android.view.Window.OnFrameMetricsAvailableListener, android.os.Handler):
+    
+SamShouldBeLast: android.view.accessibility.AccessibilityManager#addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener, android.os.Handler):
+    
+SamShouldBeLast: android.view.accessibility.AccessibilityManager#addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener, android.os.Handler):
+    
+SamShouldBeLast: android.webkit.WebChromeClient#onShowFileChooser(android.webkit.WebView, android.webkit.ValueCallback<android.net.Uri[]>, android.webkit.WebChromeClient.FileChooserParams):
+    
+SamShouldBeLast: android.webkit.WebView#setWebViewRenderProcessClient(java.util.concurrent.Executor, android.webkit.WebViewRenderProcessClient):
+    
+
+
+ServiceName: android.Manifest.permission#BIND_ATTENTION_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_AUGMENTED_AUTOFILL_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_CELL_BROADCAST_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_CONTENT_CAPTURE_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_CONTENT_SUGGESTIONS_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_EUICC_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_EXTERNAL_STORAGE_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_IMS_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_NETWORK_RECOMMENDATION_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_NOTIFICATION_ASSISTANT_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_PHONE_ACCOUNT_SUGGESTION_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_PRINT_RECOMMENDATION_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_RESOLVER_RANKER_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_SETTINGS_SUGGESTIONS_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_SOUND_TRIGGER_DETECTION_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_TELEPHONY_DATA_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_TELEPHONY_NETWORK_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_TEXTCLASSIFIER_SERVICE:
+    
+ServiceName: android.Manifest.permission#BIND_TV_REMOTE_SERVICE:
+    
+ServiceName: android.Manifest.permission#PROVIDE_RESOLVER_RANKER_SERVICE:
+    
+ServiceName: android.Manifest.permission#REQUEST_NOTIFICATION_ASSISTANT_SERVICE:
+    
+ServiceName: android.provider.DeviceConfig#NAMESPACE_PACKAGE_MANAGER_SERVICE:
+    
diff --git a/api/test-current.txt b/api/test-current.txt
index d292e01..e376c47 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -305,6 +305,7 @@
   public static final class AppOpsManager.OpEntry implements android.os.Parcelable {
     method public int describeContents();
     method public long getDuration();
+    method @NonNull public java.util.Map<java.lang.String,android.app.AppOpsManager.OpFeatureEntry> getFeatures();
     method public long getLastAccessBackgroundTime(int);
     method public long getLastAccessForegroundTime(int);
     method public long getLastAccessTime(int);
@@ -318,13 +319,35 @@
     method public long getLastRejectTime(int, int, int);
     method public int getMode();
     method @NonNull public String getOpStr();
+    method @Deprecated @Nullable public String getProxyPackageName();
+    method @Nullable public String getProxyPackageName(int, int);
+    method @Deprecated public int getProxyUid();
+    method public int getProxyUid(int, int);
+    method public boolean isRunning();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
+  }
+
+  public static final class AppOpsManager.OpFeatureEntry {
+    method public long getDuration();
+    method public long getLastAccessBackgroundTime(int);
+    method public long getLastAccessForegroundTime(int);
+    method public long getLastAccessTime(int);
+    method public long getLastAccessTime(int, int, int);
+    method public long getLastBackgroundDuration(int);
+    method public long getLastDuration(int, int, int);
+    method public long getLastForegroundDuration(int);
+    method public long getLastRejectBackgroundTime(int);
+    method public long getLastRejectForegroundTime(int);
+    method public long getLastRejectTime(int);
+    method public long getLastRejectTime(int, int, int);
+    method @Nullable public String getProxyFeatureId();
+    method @Nullable public String getProxyFeatureId(int, int);
     method @Nullable public String getProxyPackageName();
     method @Nullable public String getProxyPackageName(int, int);
     method public int getProxyUid();
     method public int getProxyUid(int, int);
     method public boolean isRunning();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
   }
 
   public class DownloadManager {
@@ -659,7 +682,7 @@
   }
 
   public abstract class Context {
-    method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle);
+    method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle, int);
     method @NonNull public android.content.Context createPackageContextAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.view.Display getDisplay();
     method public abstract int getDisplayId();
@@ -731,6 +754,7 @@
     method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.REVOKE_RUNTIME_PERMISSIONS", "android.permission.GET_RUNTIME_PERMISSIONS"}) public abstract int getPermissionFlags(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
     method @NonNull public abstract String getServicesSystemSharedLibraryPackageName();
     method @NonNull public abstract String getSharedSystemSharedLibraryPackageName();
+    method @Nullable public String[] getTelephonyPackageNames();
     method @Nullable public String getWellbeingPackageName();
     method @RequiresPermission("android.permission.GRANT_RUNTIME_PERMISSIONS") public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
     method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void removeOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
@@ -769,8 +793,10 @@
     field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000
     field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
     field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
+    field public static final int PROTECTION_FLAG_TELEPHONY = 4194304; // 0x400000
     field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000
     field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000
+    field public static final int PROTECTION_FLAG_WIFI = 8388608; // 0x800000
     field @Nullable public final String backgroundPermission;
   }
 
@@ -1097,7 +1123,9 @@
 
   public class LocationManager {
     method @NonNull public String[] getBackgroundThrottlingWhitelist();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
     method @NonNull public String[] getIgnoreSettingsWhitelist();
+    method @Nullable @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
     method @NonNull public java.util.List<android.location.LocationRequest> getTestProviderCurrentRequests(String);
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
@@ -2249,8 +2277,11 @@
 package android.permission {
 
   public final class PermissionControllerManager {
+    method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.RESTORE_RUNTIME_PERMISSIONS"}) public void applyStagedRuntimePermissionBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @RequiresPermission("android.permission.GET_RUNTIME_PERMISSIONS") public void getAppPermissions(@NonNull String, @NonNull android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, @Nullable android.os.Handler);
+    method @RequiresPermission("android.permission.GET_RUNTIME_PERMISSIONS") public void getRuntimePermissionBackup(@NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<byte[]>);
     method @RequiresPermission("android.permission.REVOKE_RUNTIME_PERMISSIONS") public void revokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull java.util.concurrent.Executor, @NonNull android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback);
+    method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.RESTORE_RUNTIME_PERMISSIONS"}) public void stageAndApplyRuntimePermissionsBackup(@NonNull byte[], @NonNull android.os.UserHandle);
     field public static final int COUNT_ONLY_WHEN_GRANTED = 1; // 0x1
     field public static final int COUNT_WHEN_SYSTEM = 2; // 0x2
     field public static final int REASON_INSTALLER_POLICY_VIOLATION = 2; // 0x2
@@ -2791,6 +2822,10 @@
     method public void exitBackgroundAudioProcessing(boolean);
   }
 
+  public static class Call.Details {
+    method public String getTelecomCallId();
+  }
+
   public final class CallAudioState implements android.os.Parcelable {
     ctor public CallAudioState(boolean, int, int, @Nullable android.bluetooth.BluetoothDevice, @NonNull java.util.Collection<android.bluetooth.BluetoothDevice>);
   }
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index e643ab5..b4fdd0b 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -180,11 +180,11 @@
 
     // Note that conditional property enablement/exclusion only applies if
     // the attribute is present. In its absence, all overlays are presumed enabled.
-    if (!overlay_info->requiredSystemPropertyName.empty()
-        && !overlay_info->requiredSystemPropertyValue.empty()) {
+    if (!overlay_info->requiredSystemPropertyName.empty() &&
+        !overlay_info->requiredSystemPropertyValue.empty()) {
       // if property set & equal to value, then include overlay - otherwise skip
-      if (android::base::GetProperty(overlay_info->requiredSystemPropertyName, "")
-          != overlay_info->requiredSystemPropertyValue) {
+      if (android::base::GetProperty(overlay_info->requiredSystemPropertyName, "") !=
+          overlay_info->requiredSystemPropertyValue) {
         continue;
       }
     }
diff --git a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
index 1a0d443..924efe5 100644
--- a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
+++ b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
@@ -34,9 +34,10 @@
   void visit(const IdmapHeader& header) override;
   void visit(const IdmapData& data) override;
   void visit(const IdmapData::Header& header) override;
-  void visit(const IdmapData::TypeEntry& type_entry) override;
 
  private:
+  void Write(const void* value, size_t length);
+  void Write8(uint8_t value);
   void Write16(uint16_t value);
   void Write32(uint32_t value);
   void WriteString(const StringPiece& value);
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index f2cae58..2639c6f 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -41,6 +41,18 @@
  * # idmap file format changelog
  * ## v1
  * - Identical to idmap v1.
+ * ## v2
+ * - Entries are no longer separated by type into type specific data blocks.
+ * - Added overlay-indexed target resource id lookup capabilities.
+ * - Target and overlay entries are stored as a sparse array in the data block. The target entries
+ *   array maps from target resource id to overlay data type and value and the array is sorted by
+ *   target resource id. The overlay entries array maps from overlay resource id to target resource
+ *   id and the array is sorted by overlay resource id. It is important for both arrays to be sorted
+ *   to allow for O(log(number_of_overlaid_resources)) performance when looking up resource
+ *   mappings at runtime.
+ * - Idmap can now encode a type and value to override a resource without needing a table entry.
+ * - A string pool block is included to retrieve the value of strings that do not have a resource
+ *   table entry.
  */
 
 #ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
@@ -125,7 +137,6 @@
   friend Idmap;
   DISALLOW_COPY_AND_ASSIGN(IdmapHeader);
 };
-
 class IdmapData {
  public:
   class Header {
@@ -136,60 +147,51 @@
       return target_package_id_;
     }
 
-    inline uint16_t GetTypeCount() const {
-      return type_count_;
+    inline PackageId GetOverlayPackageId() const {
+      return overlay_package_id_;
+    }
+
+    inline uint32_t GetTargetEntryCount() const {
+      return target_entry_count;
+    }
+
+    inline uint32_t GetOverlayEntryCount() const {
+      return overlay_entry_count;
+    }
+
+    inline uint32_t GetStringPoolIndexOffset() const {
+      return string_pool_index_offset;
+    }
+
+    inline uint32_t GetStringPoolLength() const {
+      return string_pool_len;
     }
 
     void accept(Visitor* v) const;
 
    private:
-    Header() {
-    }
-
     PackageId target_package_id_;
-    uint16_t type_count_;
+    PackageId overlay_package_id_;
+    uint32_t target_entry_count;
+    uint32_t overlay_entry_count;
+    uint32_t string_pool_index_offset;
+    uint32_t string_pool_len;
+    Header() = default;
 
+    friend Idmap;
     friend IdmapData;
     DISALLOW_COPY_AND_ASSIGN(Header);
   };
 
-  class TypeEntry {
-   public:
-    static std::unique_ptr<const TypeEntry> FromBinaryStream(std::istream& stream);
+  struct TargetEntry {
+    ResourceId target_id;
+    TargetValue::DataType data_type;
+    TargetValue::DataValue data_value;
+  };
 
-    inline TypeId GetTargetTypeId() const {
-      return target_type_id_;
-    }
-
-    inline TypeId GetOverlayTypeId() const {
-      return overlay_type_id_;
-    }
-
-    inline uint16_t GetEntryCount() const {
-      return entries_.size();
-    }
-
-    inline uint16_t GetEntryOffset() const {
-      return entry_offset_;
-    }
-
-    inline EntryId GetEntry(size_t i) const {
-      return i < entries_.size() ? entries_[i] : 0xffffu;
-    }
-
-    void accept(Visitor* v) const;
-
-   private:
-    TypeEntry() {
-    }
-
-    TypeId target_type_id_;
-    TypeId overlay_type_id_;
-    uint16_t entry_offset_;
-    std::vector<EntryId> entries_;
-
-    friend IdmapData;
-    DISALLOW_COPY_AND_ASSIGN(TypeEntry);
+  struct OverlayEntry {
+    ResourceId overlay_id;
+    ResourceId target_id;
   };
 
   static std::unique_ptr<const IdmapData> FromBinaryStream(std::istream& stream);
@@ -201,8 +203,16 @@
     return header_;
   }
 
-  inline const std::vector<std::unique_ptr<const TypeEntry>>& GetTypeEntries() const {
-    return type_entries_;
+  inline const std::vector<TargetEntry>& GetTargetEntries() const {
+    return target_entries_;
+  }
+
+  inline const std::vector<OverlayEntry>& GetOverlayEntries() const {
+    return overlay_entries_;
+  }
+
+  inline const void* GetStringPoolData() const {
+    return string_pool_.get();
   }
 
   void accept(Visitor* v) const;
@@ -212,7 +222,9 @@
   }
 
   std::unique_ptr<const Header> header_;
-  std::vector<std::unique_ptr<const TypeEntry>> type_entries_;
+  std::vector<TargetEntry> target_entries_;
+  std::vector<OverlayEntry> overlay_entries_;
+  std::unique_ptr<uint8_t[]> string_pool_;
 
   friend Idmap;
   DISALLOW_COPY_AND_ASSIGN(IdmapData);
@@ -262,7 +274,6 @@
   virtual void visit(const IdmapHeader& header) = 0;
   virtual void visit(const IdmapData& data) = 0;
   virtual void visit(const IdmapData::Header& header) = 0;
-  virtual void visit(const IdmapData::TypeEntry& type_entry) = 0;
 };
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
index f0f141a..5dcf217 100644
--- a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
@@ -38,13 +38,11 @@
   void visit(const IdmapHeader& header) override;
   void visit(const IdmapData& data) override;
   void visit(const IdmapData::Header& header) override;
-  void visit(const IdmapData::TypeEntry& type_entry) override;
 
  private:
   std::ostream& stream_;
   std::unique_ptr<const ApkAssets> target_apk_;
   AssetManager2 target_am_;
-  PackageId last_seen_package_id_;
 };
 
 }  // namespace idmap2
diff --git a/cmds/idmap2/include/idmap2/RawPrintVisitor.h b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
index cd38971..76475ab 100644
--- a/cmds/idmap2/include/idmap2/RawPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
@@ -39,18 +39,20 @@
   void visit(const IdmapHeader& header) override;
   void visit(const IdmapData& data) override;
   void visit(const IdmapData::Header& header) override;
-  void visit(const IdmapData::TypeEntry& type_entry) override;
 
  private:
+  void print(uint8_t value, const char* fmt, ...);
   void print(uint16_t value, const char* fmt, ...);
   void print(uint32_t value, const char* fmt, ...);
   void print(const std::string& value, const char* fmt, ...);
+  void print_raw(uint32_t length, const char* fmt, ...);
 
   std::ostream& stream_;
   std::unique_ptr<const ApkAssets> target_apk_;
+  std::unique_ptr<const ApkAssets> overlay_apk_;
   AssetManager2 target_am_;
+  AssetManager2 overlay_am_;
   size_t offset_;
-  PackageId last_seen_package_id_;
 };
 
 }  // namespace idmap2
diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h
index abc2df1..de1dbc9 100644
--- a/cmds/idmap2/include/idmap2/ResourceUtils.h
+++ b/cmds/idmap2/include/idmap2/ResourceUtils.h
@@ -37,14 +37,16 @@
 
 namespace utils {
 
+StringPiece DataTypeToString(uint8_t data_type);
+
 struct OverlayManifestInfo {
-  std::string target_package;  // NOLINT(misc-non-private-member-variables-in-classes)
-  std::string target_name;     // NOLINT(misc-non-private-member-variables-in-classes)
-  std::string requiredSystemPropertyName;  // NOLINT(misc-non-private-member-variables-in-classes)
+  std::string target_package;               // NOLINT(misc-non-private-member-variables-in-classes)
+  std::string target_name;                  // NOLINT(misc-non-private-member-variables-in-classes)
+  std::string requiredSystemPropertyName;   // NOLINT(misc-non-private-member-variables-in-classes)
   std::string requiredSystemPropertyValue;  // NOLINT(misc-non-private-member-variables-in-classes)
-  uint32_t resource_mapping;   // NOLINT(misc-non-private-member-variables-in-classes)
-  bool is_static;              // NOLINT(misc-non-private-member-variables-in-classes)
-  int priority = -1;           // NOLINT(misc-non-private-member-variables-in-classes)
+  uint32_t resource_mapping;                // NOLINT(misc-non-private-member-variables-in-classes)
+  bool is_static;                           // NOLINT(misc-non-private-member-variables-in-classes)
+  int priority = -1;                        // NOLINT(misc-non-private-member-variables-in-classes)
 };
 
 Result<OverlayManifestInfo> ExtractOverlayManifestInfo(const std::string& path,
diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
index dee2d21..3b0940a 100644
--- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
+++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
@@ -24,6 +24,14 @@
 
 namespace android::idmap2 {
 
+void BinaryStreamVisitor::Write(const void* value, size_t length) {
+  stream_.write(reinterpret_cast<const char*>(value), length);
+}
+
+void BinaryStreamVisitor::Write8(uint8_t value) {
+  stream_.write(reinterpret_cast<char*>(&value), sizeof(uint8_t));
+}
+
 void BinaryStreamVisitor::Write16(uint16_t value) {
   uint16_t x = htodl(value);
   stream_.write(reinterpret_cast<char*>(&x), sizeof(uint16_t));
@@ -54,26 +62,28 @@
   WriteString(header.GetOverlayPath());
 }
 
-void BinaryStreamVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
-  // nothing to do
+void BinaryStreamVisitor::visit(const IdmapData& data) {
+  for (const auto& target_entry : data.GetTargetEntries()) {
+    Write32(target_entry.target_id);
+    Write8(target_entry.data_type);
+    Write32(target_entry.data_value);
+  }
+
+  for (const auto& overlay_entry : data.GetOverlayEntries()) {
+    Write32(overlay_entry.overlay_id);
+    Write32(overlay_entry.target_id);
+  }
+
+  Write(data.GetStringPoolData(), data.GetHeader()->GetStringPoolLength());
 }
 
 void BinaryStreamVisitor::visit(const IdmapData::Header& header) {
-  Write16(header.GetTargetPackageId());
-  Write16(header.GetTypeCount());
-}
-
-void BinaryStreamVisitor::visit(const IdmapData::TypeEntry& type_entry) {
-  const uint16_t entryCount = type_entry.GetEntryCount();
-
-  Write16(type_entry.GetTargetTypeId());
-  Write16(type_entry.GetOverlayTypeId());
-  Write16(entryCount);
-  Write16(type_entry.GetEntryOffset());
-  for (uint16_t i = 0; i < entryCount; i++) {
-    EntryId entry_id = type_entry.GetEntry(i);
-    Write32(entry_id != kNoEntry ? static_cast<uint32_t>(entry_id) : kPadding);
-  }
+  Write8(header.GetTargetPackageId());
+  Write8(header.GetOverlayPackageId());
+  Write32(header.GetTargetEntryCount());
+  Write32(header.GetOverlayEntryCount());
+  Write32(header.GetStringPoolIndexOffset());
+  Write32(header.GetStringPoolLength());
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 389ade5..5cb91d7 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -42,30 +42,10 @@
 
 namespace {
 
-class MatchingResources {
- public:
-  void Add(ResourceId target_resid, ResourceId overlay_resid) {
-    TypeId target_typeid = EXTRACT_TYPE(target_resid);
-    if (map_.find(target_typeid) == map_.end()) {
-      map_.emplace(target_typeid, std::set<std::pair<ResourceId, ResourceId>>());
-    }
-    map_[target_typeid].insert(std::make_pair(target_resid, overlay_resid));
-  }
-
-  inline const std::map<TypeId, std::set<std::pair<ResourceId, ResourceId>>>& WARN_UNUSED
-  Map() const {
-    return map_;
-  }
-
- private:
-  // target type id -> set { pair { overlay entry id, overlay entry id } }
-  std::map<TypeId, std::set<std::pair<ResourceId, ResourceId>>> map_;
-};
-
-bool WARN_UNUSED Read16(std::istream& stream, uint16_t* out) {
-  uint16_t value;
-  if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint16_t))) {
-    *out = dtohl(value);
+bool WARN_UNUSED Read8(std::istream& stream, uint8_t* out) {
+  uint8_t value;
+  if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint8_t))) {
+    *out = value;
     return true;
   }
   return false;
@@ -80,6 +60,15 @@
   return false;
 }
 
+bool WARN_UNUSED ReadBuffer(std::istream& stream, std::unique_ptr<uint8_t[]>* out, size_t length) {
+  auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[length]);
+  if (stream.read(reinterpret_cast<char*>(buffer.get()), length)) {
+    *out = std::move(buffer);
+    return true;
+  }
+  return false;
+}
+
 // a string is encoded as a kIdmapStringLength char array; the array is always null-terminated
 bool WARN_UNUSED ReadString(std::istream& stream, char out[kIdmapStringLength]) {
   char buf[kIdmapStringLength];
@@ -162,51 +151,48 @@
 std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std::istream& stream) {
   std::unique_ptr<IdmapData::Header> idmap_data_header(new IdmapData::Header());
 
-  uint16_t target_package_id16;
-  if (!Read16(stream, &target_package_id16) || !Read16(stream, &idmap_data_header->type_count_)) {
+  if (!Read8(stream, &idmap_data_header->target_package_id_) ||
+      !Read8(stream, &idmap_data_header->overlay_package_id_) ||
+      !Read32(stream, &idmap_data_header->target_entry_count) ||
+      !Read32(stream, &idmap_data_header->overlay_entry_count) ||
+      !Read32(stream, &idmap_data_header->string_pool_index_offset) ||
+      !Read32(stream, &idmap_data_header->string_pool_len)) {
     return nullptr;
   }
-  idmap_data_header->target_package_id_ = target_package_id16;
 
   return std::move(idmap_data_header);
 }
 
-std::unique_ptr<const IdmapData::TypeEntry> IdmapData::TypeEntry::FromBinaryStream(
-    std::istream& stream) {
-  std::unique_ptr<IdmapData::TypeEntry> data(new IdmapData::TypeEntry());
-  uint16_t target_type16;
-  uint16_t overlay_type16;
-  uint16_t entry_count;
-  if (!Read16(stream, &target_type16) || !Read16(stream, &overlay_type16) ||
-      !Read16(stream, &entry_count) || !Read16(stream, &data->entry_offset_)) {
-    return nullptr;
-  }
-  data->target_type_id_ = target_type16;
-  data->overlay_type_id_ = overlay_type16;
-  for (uint16_t i = 0; i < entry_count; i++) {
-    ResourceId resid;
-    if (!Read32(stream, &resid)) {
-      return nullptr;
-    }
-    data->entries_.push_back(resid);
-  }
-
-  return std::move(data);
-}
-
 std::unique_ptr<const IdmapData> IdmapData::FromBinaryStream(std::istream& stream) {
   std::unique_ptr<IdmapData> data(new IdmapData());
   data->header_ = IdmapData::Header::FromBinaryStream(stream);
   if (!data->header_) {
     return nullptr;
   }
-  for (size_t type_count = 0; type_count < data->header_->GetTypeCount(); type_count++) {
-    std::unique_ptr<const TypeEntry> type = IdmapData::TypeEntry::FromBinaryStream(stream);
-    if (!type) {
+  // Read the mapping of target resource id to overlay resource value.
+  for (size_t i = 0; i < data->header_->GetTargetEntryCount(); i++) {
+    TargetEntry target_entry{};
+    if (!Read32(stream, &target_entry.target_id) || !Read8(stream, &target_entry.data_type) ||
+        !Read32(stream, &target_entry.data_value)) {
       return nullptr;
     }
-    data->type_entries_.push_back(std::move(type));
+    data->target_entries_.emplace_back(target_entry);
   }
+
+  // Read the mapping of overlay resource id to target resource id.
+  for (size_t i = 0; i < data->header_->GetOverlayEntryCount(); i++) {
+    OverlayEntry overlay_entry{};
+    if (!Read32(stream, &overlay_entry.overlay_id) || !Read32(stream, &overlay_entry.target_id)) {
+      return nullptr;
+    }
+    data->overlay_entries_.emplace_back(overlay_entry);
+  }
+
+  // Read raw string pool bytes.
+  if (!ReadBuffer(stream, &data->string_pool_, data->header_->string_pool_len)) {
+    return nullptr;
+  }
+
   return std::move(data);
 }
 
@@ -247,40 +233,28 @@
     return Error("no resources were overlaid");
   }
 
-  MatchingResources matching_resources;
-  for (const auto mapping : resource_mapping.GetTargetToOverlayMap()) {
-    if (mapping.second.data_type != Res_value::TYPE_REFERENCE) {
-      // The idmap format must change to support non-references.
-      continue;
-    }
-
-    matching_resources.Add(mapping.first, mapping.second.data_value);
+  std::unique_ptr<IdmapData> data(new IdmapData());
+  for (const auto& mappings : resource_mapping.GetTargetToOverlayMap()) {
+    data->target_entries_.emplace_back(IdmapData::TargetEntry{
+        mappings.first, mappings.second.data_type, mappings.second.data_value});
   }
 
-  // encode idmap data
-  std::unique_ptr<IdmapData> data(new IdmapData());
-  const auto types_end = matching_resources.Map().cend();
-  for (auto ti = matching_resources.Map().cbegin(); ti != types_end; ++ti) {
-    auto ei = ti->second.cbegin();
-    std::unique_ptr<IdmapData::TypeEntry> type(new IdmapData::TypeEntry());
-    type->target_type_id_ = EXTRACT_TYPE(ei->first);
-    type->overlay_type_id_ = EXTRACT_TYPE(ei->second);
-    type->entry_offset_ = EXTRACT_ENTRY(ei->first);
-    EntryId last_target_entry = kNoEntry;
-    for (; ei != ti->second.cend(); ++ei) {
-      if (last_target_entry != kNoEntry) {
-        int count = EXTRACT_ENTRY(ei->first) - last_target_entry - 1;
-        type->entries_.insert(type->entries_.end(), count, kNoEntry);
-      }
-      type->entries_.push_back(EXTRACT_ENTRY(ei->second));
-      last_target_entry = EXTRACT_ENTRY(ei->first);
-    }
-    data->type_entries_.push_back(std::move(type));
+  for (const auto& mappings : resource_mapping.GetOverlayToTargetMap()) {
+    data->overlay_entries_.emplace_back(IdmapData::OverlayEntry{mappings.first, mappings.second});
   }
 
   std::unique_ptr<IdmapData::Header> data_header(new IdmapData::Header());
   data_header->target_package_id_ = resource_mapping.GetTargetPackageId();
-  data_header->type_count_ = data->type_entries_.size();
+  data_header->overlay_package_id_ = resource_mapping.GetOverlayPackageId();
+  data_header->target_entry_count = static_cast<uint32_t>(data->target_entries_.size());
+  data_header->overlay_entry_count = static_cast<uint32_t>(data->overlay_entries_.size());
+  data_header->string_pool_index_offset = resource_mapping.GetStringPoolOffset();
+
+  const auto string_pool_data = resource_mapping.GetStringPoolData();
+  data_header->string_pool_len = string_pool_data.second;
+  data->string_pool_ = std::unique_ptr<uint8_t[]>(new uint8_t[data_header->string_pool_len]);
+  memcpy(data->string_pool_.get(), string_pool_data.first, data_header->string_pool_len);
+
   data->header_ = std::move(data_header);
   return {std::move(data)};
 }
@@ -367,25 +341,16 @@
   v->visit(*this);
 }
 
-void IdmapData::TypeEntry::accept(Visitor* v) const {
-  assert(v != nullptr);
-  v->visit(*this);
-}
-
 void IdmapData::accept(Visitor* v) const {
   assert(v != nullptr);
-  v->visit(*this);
   header_->accept(v);
-  auto end = type_entries_.cend();
-  for (auto iter = type_entries_.cbegin(); iter != end; ++iter) {
-    (*iter)->accept(v);
-  }
+  v->visit(*this);
 }
 
 void Idmap::accept(Visitor* v) const {
   assert(v != nullptr);
-  v->visit(*this);
   header_->accept(v);
+  v->visit(*this);
   auto end = data_.cend();
   for (auto iter = data_.cbegin(); iter != end; ++iter) {
     (*iter)->accept(v);
diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
index fbf2c77..a662aa5 100644
--- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
@@ -41,29 +41,33 @@
   }
 }
 
-void PrettyPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
-}
-
 void PrettyPrintVisitor::visit(const IdmapData::Header& header ATTRIBUTE_UNUSED) {
-  last_seen_package_id_ = header.GetTargetPackageId();
 }
 
-void PrettyPrintVisitor::visit(const IdmapData::TypeEntry& type_entry) {
+void PrettyPrintVisitor::visit(const IdmapData& data) {
   const bool target_package_loaded = !target_am_.GetApkAssets().empty();
-  for (uint16_t i = 0; i < type_entry.GetEntryCount(); i++) {
-    const EntryId entry = type_entry.GetEntry(i);
-    if (entry == kNoEntry) {
-      continue;
+  const ResStringPool string_pool(data.GetStringPoolData(),
+                                  data.GetHeader()->GetStringPoolLength());
+  const size_t string_pool_offset = data.GetHeader()->GetStringPoolIndexOffset();
+
+  for (auto& target_entry : data.GetTargetEntries()) {
+    stream_ << base::StringPrintf("0x%08x ->", target_entry.target_id);
+
+    if (target_entry.data_type != Res_value::TYPE_REFERENCE &&
+        target_entry.data_type != Res_value::TYPE_DYNAMIC_REFERENCE) {
+      stream_ << " " << utils::DataTypeToString(target_entry.data_type);
     }
 
-    const ResourceId target_resid =
-        RESID(last_seen_package_id_, type_entry.GetTargetTypeId(), type_entry.GetEntryOffset() + i);
-    const ResourceId overlay_resid =
-        RESID(last_seen_package_id_, type_entry.GetOverlayTypeId(), entry);
+    if (target_entry.data_type == Res_value::TYPE_STRING) {
+      stream_ << " \""
+              << string_pool.string8ObjectAt(target_entry.data_value - string_pool_offset).c_str()
+              << "\"";
+    } else {
+      stream_ << " " << base::StringPrintf("0x%08x", target_entry.data_value);
+    }
 
-    stream_ << base::StringPrintf("0x%08x -> 0x%08x", target_resid, overlay_resid);
     if (target_package_loaded) {
-      Result<std::string> name = utils::ResToTypeEntryName(target_am_, target_resid);
+      Result<std::string> name = utils::ResToTypeEntryName(target_am_, target_entry.target_id);
       if (name) {
         stream_ << " " << *name;
       }
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index dd14fd4..13973d6 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -47,46 +47,94 @@
   if (target_apk_) {
     target_am_.SetApkAssets({target_apk_.get()});
   }
+
+  overlay_apk_ = ApkAssets::Load(header.GetOverlayPath().to_string());
+  if (overlay_apk_) {
+    overlay_am_.SetApkAssets({overlay_apk_.get()});
+  }
 }
 
 void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
+  const bool target_package_loaded = !target_am_.GetApkAssets().empty();
+  const bool overlay_package_loaded = !overlay_am_.GetApkAssets().empty();
+
+  for (auto& target_entry : data.GetTargetEntries()) {
+    Result<std::string> target_name(Error(""));
+    if (target_package_loaded) {
+      target_name = utils::ResToTypeEntryName(target_am_, target_entry.target_id);
+    }
+    if (target_name) {
+      print(target_entry.target_id, "target id: %s", target_name->c_str());
+    } else {
+      print(target_entry.target_id, "target id");
+    }
+
+    print(target_entry.data_type, "type: %s",
+          utils::DataTypeToString(target_entry.data_type).data());
+
+    Result<std::string> overlay_name(Error(""));
+    if (overlay_package_loaded && (target_entry.data_type == Res_value::TYPE_REFERENCE ||
+                                   target_entry.data_type == Res_value::TYPE_DYNAMIC_REFERENCE)) {
+      overlay_name = utils::ResToTypeEntryName(overlay_am_, target_entry.data_value);
+    }
+    if (overlay_name) {
+      print(target_entry.data_value, "value: %s", overlay_name->c_str());
+    } else {
+      print(target_entry.data_value, "value");
+    }
+  }
+
+  for (auto& overlay_entry : data.GetOverlayEntries()) {
+    Result<std::string> overlay_name(Error(""));
+    if (overlay_package_loaded) {
+      overlay_name = utils::ResToTypeEntryName(overlay_am_, overlay_entry.overlay_id);
+    }
+
+    if (overlay_name) {
+      print(overlay_entry.overlay_id, "overlay id: %s", overlay_name->c_str());
+    } else {
+      print(overlay_entry.overlay_id, "overlay id");
+    }
+
+    Result<std::string> target_name(Error(""));
+    if (target_package_loaded) {
+      target_name = utils::ResToTypeEntryName(target_am_, overlay_entry.target_id);
+    }
+
+    if (target_name) {
+      print(overlay_entry.target_id, "target id: %s", target_name->c_str());
+    } else {
+      print(overlay_entry.target_id, "target id");
+    }
+  }
+
+  const size_t string_pool_length = data.GetHeader()->GetStringPoolLength();
+  if (string_pool_length > 0) {
+    print_raw(string_pool_length, "%zu raw string pool bytes", string_pool_length);
+  }
 }
 
 void RawPrintVisitor::visit(const IdmapData::Header& header) {
-  print(static_cast<uint16_t>(header.GetTargetPackageId()), "target package id");
-  print(header.GetTypeCount(), "type count");
-  last_seen_package_id_ = header.GetTargetPackageId();
+  print(header.GetTargetPackageId(), "target package id");
+  print(header.GetOverlayPackageId(), "overlay package id");
+  print(header.GetTargetEntryCount(), "target entry count");
+  print(header.GetOverlayEntryCount(), "overlay entry count");
+  print(header.GetStringPoolIndexOffset(), "string pool index offset");
+  print(header.GetStringPoolLength(), "string pool byte length");
 }
 
-void RawPrintVisitor::visit(const IdmapData::TypeEntry& type_entry) {
-  const bool target_package_loaded = !target_am_.GetApkAssets().empty();
+// NOLINTNEXTLINE(cert-dcl50-cpp)
+void RawPrintVisitor::print(uint8_t value, const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  std::string comment;
+  base::StringAppendV(&comment, fmt, ap);
+  va_end(ap);
 
-  print(static_cast<uint16_t>(type_entry.GetTargetTypeId()), "target type");
-  print(static_cast<uint16_t>(type_entry.GetOverlayTypeId()), "overlay type");
-  print(static_cast<uint16_t>(type_entry.GetEntryCount()), "entry count");
-  print(static_cast<uint16_t>(type_entry.GetEntryOffset()), "entry offset");
+  stream_ << base::StringPrintf("%08zx:       %02x", offset_, value) << "  " << comment
+          << std::endl;
 
-  for (uint16_t i = 0; i < type_entry.GetEntryCount(); i++) {
-    const EntryId entry = type_entry.GetEntry(i);
-    if (entry == kNoEntry) {
-      print(kPadding, "no entry");
-    } else {
-      const ResourceId target_resid = RESID(last_seen_package_id_, type_entry.GetTargetTypeId(),
-                                            type_entry.GetEntryOffset() + i);
-      const ResourceId overlay_resid =
-          RESID(last_seen_package_id_, type_entry.GetOverlayTypeId(), entry);
-      Result<std::string> name(Error(""));
-      if (target_package_loaded) {
-        name = utils::ResToTypeEntryName(target_am_, target_resid);
-      }
-      if (name) {
-        print(static_cast<uint32_t>(entry), "0x%08x -> 0x%08x %s", target_resid, overlay_resid,
-              name->c_str());
-      } else {
-        print(static_cast<uint32_t>(entry), "0x%08x -> 0x%08x", target_resid, overlay_resid);
-      }
-    }
-  }
+  offset_ += sizeof(uint8_t);
 }
 
 // NOLINTNEXTLINE(cert-dcl50-cpp)
@@ -123,10 +171,23 @@
   base::StringAppendV(&comment, fmt, ap);
   va_end(ap);
 
-  stream_ << base::StringPrintf("%08zx: ", offset_) << "........ " << comment << ": " << value
+  stream_ << base::StringPrintf("%08zx: ", offset_) << "........  " << comment << ": " << value
           << std::endl;
 
   offset_ += kIdmapStringLength;
 }
 
+// NOLINTNEXTLINE(cert-dcl50-cpp)
+void RawPrintVisitor::print_raw(uint32_t length, const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  std::string comment;
+  base::StringAppendV(&comment, fmt, ap);
+  va_end(ap);
+
+  stream_ << base::StringPrintf("%08zx: ", offset_) << "........  " << comment << std::endl;
+
+  offset_ += length;
+}
+
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp
index 95ae626..651d20f 100644
--- a/cmds/idmap2/libidmap2/ResourceMapping.cpp
+++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp
@@ -192,9 +192,14 @@
     // Only rewrite resources defined within the overlay package to their corresponding target
     // resource ids at runtime.
     bool rewrite_overlay_reference =
-        (overlay_resource->dataType == Res_value::TYPE_REFERENCE)
+        (overlay_resource->dataType == Res_value::TYPE_REFERENCE ||
+         overlay_resource->dataType == Res_value::TYPE_DYNAMIC_REFERENCE)
             ? overlay_package_id == EXTRACT_PACKAGE(overlay_resource->data)
             : false;
+    
+    if (rewrite_overlay_reference) {
+      overlay_resource->dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
+    }
 
     resource_mapping.AddMapping(target_id, overlay_resource->dataType, overlay_resource->data,
                                 rewrite_overlay_reference);
@@ -224,7 +229,7 @@
     }
 
     resource_mapping.AddMapping(target_resource, Res_value::TYPE_REFERENCE, overlay_resid,
-                                /* rewrite_overlay_reference */ true);
+                                /* rewrite_overlay_reference */ false);
   }
 
   return resource_mapping;
@@ -378,7 +383,8 @@
 
   target_map_.insert(std::make_pair(target_resource, TargetValue{data_type, data_value}));
 
-  if (rewrite_overlay_reference && data_type == Res_value::TYPE_REFERENCE) {
+  if (rewrite_overlay_reference &&
+      (data_type == Res_value::TYPE_REFERENCE || data_type == Res_value::TYPE_DYNAMIC_REFERENCE)) {
     overlay_map_.insert(std::make_pair(data_value, target_resource));
   }
 
@@ -394,8 +400,8 @@
   const TargetValue value = target_iter->second;
   target_map_.erase(target_iter);
 
-  // Remove rewriting of overlay resource id to target resource id.
-  if (value.data_type != Res_value::TYPE_REFERENCE) {
+  if (value.data_type != Res_value::TYPE_REFERENCE &&
+      value.data_type != Res_value::TYPE_DYNAMIC_REFERENCE) {
     return;
   }
 
diff --git a/cmds/idmap2/libidmap2/ResourceUtils.cpp b/cmds/idmap2/libidmap2/ResourceUtils.cpp
index 9d32692..a5df746 100644
--- a/cmds/idmap2/libidmap2/ResourceUtils.cpp
+++ b/cmds/idmap2/libidmap2/ResourceUtils.cpp
@@ -33,6 +33,40 @@
 
 namespace android::idmap2::utils {
 
+StringPiece DataTypeToString(uint8_t data_type) {
+  switch (data_type) {
+    case Res_value::TYPE_NULL:
+      return "null";
+    case Res_value::TYPE_REFERENCE:
+      return "reference";
+    case Res_value::TYPE_ATTRIBUTE:
+      return "attribute";
+    case Res_value::TYPE_STRING:
+      return "string";
+    case Res_value::TYPE_FLOAT:
+      return "float";
+    case Res_value::TYPE_DIMENSION:
+      return "dimension";
+    case Res_value::TYPE_FRACTION:
+      return "fraction";
+    case Res_value::TYPE_DYNAMIC_REFERENCE:
+      return "reference (dynamic)";
+    case Res_value::TYPE_DYNAMIC_ATTRIBUTE:
+      return "attribute (dynamic)";
+    case Res_value::TYPE_INT_DEC:
+    case Res_value::TYPE_INT_HEX:
+      return "integer";
+    case Res_value::TYPE_INT_BOOLEAN:
+      return "boolean";
+    case Res_value::TYPE_INT_COLOR_ARGB8:
+    case Res_value::TYPE_INT_COLOR_RGB8:
+    case Res_value::TYPE_INT_COLOR_RGB4:
+      return "color";
+    default:
+      return "unknown";
+  }
+}
+
 Result<std::string> ResToTypeEntryName(const AssetManager2& am, uint32_t resid) {
   AssetManager2::ResourceName name;
   if (!am.GetResourceName(resid, &name)) {
@@ -129,7 +163,7 @@
     info.requiredSystemPropertyName = *result_str;
   }
 
-   if (auto result_str = overlay_it->GetAttributeStringValue("requiredSystemPropertyValue")) {
+  if (auto result_str = overlay_it->GetAttributeStringValue("requiredSystemPropertyValue")) {
     info.requiredSystemPropertyValue = *result_str;
   }
 
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index 43fdc9a..db4778c 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -18,6 +18,7 @@
 #include <sstream>
 #include <string>
 #include <utility>
+#include <vector>
 
 #include "TestHelpers.h"
 #include "androidfw/ApkAssets.h"
@@ -52,112 +53,39 @@
   ASSERT_EQ(idmap1->GetData().size(), 1U);
   ASSERT_EQ(idmap1->GetData().size(), idmap2->GetData().size());
 
-  const auto& data1 = idmap1->GetData()[0];
-  const auto& data2 = idmap2->GetData()[0];
+  const std::vector<std::unique_ptr<const IdmapData>>& data_blocks1 = idmap1->GetData();
+  ASSERT_EQ(data_blocks1.size(), 1U);
+  const std::unique_ptr<const IdmapData>& data1 = data_blocks1[0];
+  ASSERT_THAT(data1, NotNull());
 
-  ASSERT_EQ(data1->GetHeader()->GetTargetPackageId(), data2->GetHeader()->GetTargetPackageId());
-  ASSERT_EQ(data1->GetTypeEntries().size(), 2U);
-  ASSERT_EQ(data1->GetTypeEntries().size(), data2->GetTypeEntries().size());
-  ASSERT_EQ(data1->GetTypeEntries()[0]->GetEntry(0), data2->GetTypeEntries()[0]->GetEntry(0));
-  ASSERT_EQ(data1->GetTypeEntries()[0]->GetEntry(1), data2->GetTypeEntries()[0]->GetEntry(1));
-  ASSERT_EQ(data1->GetTypeEntries()[0]->GetEntry(2), data2->GetTypeEntries()[0]->GetEntry(2));
-  ASSERT_EQ(data1->GetTypeEntries()[1]->GetEntry(0), data2->GetTypeEntries()[1]->GetEntry(0));
-  ASSERT_EQ(data1->GetTypeEntries()[1]->GetEntry(1), data2->GetTypeEntries()[1]->GetEntry(1));
-  ASSERT_EQ(data1->GetTypeEntries()[1]->GetEntry(2), data2->GetTypeEntries()[1]->GetEntry(2));
-}
+  const std::vector<std::unique_ptr<const IdmapData>>& data_blocks2 = idmap2->GetData();
+  ASSERT_EQ(data_blocks2.size(), 1U);
+  const std::unique_ptr<const IdmapData>& data2 = data_blocks2[0];
+  ASSERT_THAT(data2, NotNull());
 
-TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
+  const auto& target_entries1 = data1->GetTargetEntries();
+  const auto& target_entries2 = data2->GetTargetEntries();
+  ASSERT_EQ(target_entries1.size(), target_entries2.size());
+  ASSERT_EQ(target_entries1[0].target_id, target_entries2[0].target_id);
+  ASSERT_EQ(target_entries1[0].data_value, target_entries2[0].data_value);
 
-  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
+  ASSERT_EQ(target_entries1[1].target_id, target_entries2[1].target_id);
+  ASSERT_EQ(target_entries1[1].data_value, target_entries2[1].data_value);
 
-  const auto idmap = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
-                                          /* enforce_overlayable */ true);
-  ASSERT_TRUE(idmap);
+  ASSERT_EQ(target_entries1[2].target_id, target_entries2[2].target_id);
+  ASSERT_EQ(target_entries1[2].data_value, target_entries2[2].data_value);
 
-  std::stringstream stream;
-  BinaryStreamVisitor visitor(stream);
-  (*idmap)->accept(&visitor);
-  const std::string str = stream.str();
-  const StringPiece data(str);
-  std::unique_ptr<const LoadedIdmap> loaded_idmap = LoadedIdmap::Load(data);
-  ASSERT_THAT(loaded_idmap, NotNull());
-  ASSERT_EQ(loaded_idmap->TargetPackageId(), 0x7f);
+  const auto& overlay_entries1 = data1->GetOverlayEntries();
+  const auto& overlay_entries2 = data2->GetOverlayEntries();
+  ASSERT_EQ(overlay_entries1.size(), overlay_entries2.size());
+  ASSERT_EQ(overlay_entries1[0].overlay_id, overlay_entries2[0].overlay_id);
+  ASSERT_EQ(overlay_entries1[0].target_id, overlay_entries2[0].target_id);
 
-  const IdmapEntry_header* header = loaded_idmap->GetEntryMapForType(0x01);
-  ASSERT_THAT(header, NotNull());
+  ASSERT_EQ(overlay_entries1[1].overlay_id, overlay_entries2[1].overlay_id);
+  ASSERT_EQ(overlay_entries1[1].target_id, overlay_entries2[1].target_id);
 
-  EntryId entry;
-  bool success = LoadedIdmap::Lookup(header, 0x0000, &entry);
-  ASSERT_TRUE(success);
-  ASSERT_EQ(entry, 0x0000);
-
-  header = loaded_idmap->GetEntryMapForType(0x02);
-  ASSERT_THAT(header, NotNull());
-
-  success = LoadedIdmap::Lookup(header, 0x0000, &entry);  // string/a
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0001, &entry);  // string/b
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0002, &entry);  // string/c
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0003, &entry);  // string/policy_odm
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0004, &entry);  // string/policy_oem
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0005, &entry);  // string/other
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0006, &entry);  // string/not_overlayable
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0007, &entry);  // string/policy_product
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0008, &entry);  // string/policy_public
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0009, &entry);  // string/policy_system
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x000a, &entry);  // string/policy_system_vendor
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x000b, &entry);  // string/policy_signature
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x000c, &entry);  // string/str1
-  ASSERT_TRUE(success);
-  ASSERT_EQ(entry, 0x0000);
-
-  success = LoadedIdmap::Lookup(header, 0x000d, &entry);  // string/str2
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x000e, &entry);  // string/str3
-  ASSERT_TRUE(success);
-  ASSERT_EQ(entry, 0x0001);
-
-  success = LoadedIdmap::Lookup(header, 0x000f, &entry);  // string/str4
-  ASSERT_TRUE(success);
-  ASSERT_EQ(entry, 0x0002);
-
-  success = LoadedIdmap::Lookup(header, 0x0010, &entry);  // string/x
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0011, &entry);  // string/y
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0012, &entry);  // string/z
-  ASSERT_FALSE(success);
+  ASSERT_EQ(overlay_entries1[2].overlay_id, overlay_entries2[2].overlay_id);
+  ASSERT_EQ(overlay_entries1[2].target_id, overlay_entries2[2].target_id);
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index 8a48f4b..b535f30 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -131,7 +131,6 @@
   ASSERT_NE(result->stdout.find("0x7f02000c -> 0x7f020000 string/str1"), std::string::npos);
   ASSERT_NE(result->stdout.find("0x7f02000e -> 0x7f020001 string/str3"), std::string::npos);
   ASSERT_NE(result->stdout.find("0x7f02000f -> 0x7f020002 string/str4"), std::string::npos);
-  ASSERT_EQ(result->stdout.find("00000210:     007f  target package id"), std::string::npos);
 
   // clang-format off
   result = ExecuteBinary({"idmap2",
@@ -142,7 +141,6 @@
   ASSERT_THAT(result, NotNull());
   ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
   ASSERT_NE(result->stdout.find("00000000: 504d4449  magic"), std::string::npos);
-  ASSERT_NE(result->stdout.find("00000210:     007f  target package id"), std::string::npos);
 
   // clang-format off
   result = ExecuteBinary({"idmap2",
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 47e5b17..cd816dd 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -31,11 +31,21 @@
 #include "idmap2/CommandLineOptions.h"
 #include "idmap2/Idmap.h"
 
+using android::Res_value;
 using ::testing::IsNull;
 using ::testing::NotNull;
 
 namespace android::idmap2 {
 
+#define ASSERT_TARGET_ENTRY(entry, target_resid, type, value) \
+  ASSERT_EQ(entry.target_id, target_resid);                   \
+  ASSERT_EQ(entry.data_type, type);                           \
+  ASSERT_EQ(entry.data_value, value)
+
+#define ASSERT_OVERLAY_ENTRY(entry, overlay_resid, target_resid) \
+  ASSERT_EQ(entry.overlay_id, overlay_resid);                    \
+  ASSERT_EQ(entry.target_id, target_resid)
+
 TEST(IdmapTests, TestCanonicalIdmapPathFor) {
   ASSERT_EQ(Idmap::CanonicalIdmapPathFor("/foo", "/vendor/overlay/bar.apk"),
             "/foo/vendor@overlay@bar.apk@idmap");
@@ -47,11 +57,11 @@
   std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
   ASSERT_THAT(header, NotNull());
   ASSERT_EQ(header->GetMagic(), 0x504d4449U);
-  ASSERT_EQ(header->GetVersion(), 0x01U);
+  ASSERT_EQ(header->GetVersion(), 0x02U);
   ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
   ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
-  ASSERT_EQ(header->GetTargetPath().to_string(), "target.apk");
-  ASSERT_EQ(header->GetOverlayPath().to_string(), "overlay.apk");
+  ASSERT_EQ(header->GetTargetPath().to_string(), "targetX.apk");
+  ASSERT_EQ(header->GetOverlayPath().to_string(), "overlayX.apk");
 }
 
 TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
@@ -73,23 +83,8 @@
 
   std::unique_ptr<const IdmapData::Header> header = IdmapData::Header::FromBinaryStream(stream);
   ASSERT_THAT(header, NotNull());
-  ASSERT_EQ(header->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(header->GetTypeCount(), 2U);
-}
-
-TEST(IdmapTests, CreateIdmapDataResourceTypeFromBinaryStream) {
-  const size_t offset = 0x214;
-  std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
-                  idmap_raw_data_len - offset);
-  std::istringstream stream(raw);
-
-  std::unique_ptr<const IdmapData::TypeEntry> data = IdmapData::TypeEntry::FromBinaryStream(stream);
-  ASSERT_THAT(data, NotNull());
-  ASSERT_EQ(data->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(data->GetOverlayTypeId(), 0x02U);
-  ASSERT_EQ(data->GetEntryCount(), 1U);
-  ASSERT_EQ(data->GetEntryOffset(), 0U);
-  ASSERT_EQ(data->GetEntry(0), 0U);
+  ASSERT_EQ(header->GetTargetEntryCount(), 0x03);
+  ASSERT_EQ(header->GetOverlayEntryCount(), 0x03);
 }
 
 TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
@@ -100,24 +95,21 @@
 
   std::unique_ptr<const IdmapData> data = IdmapData::FromBinaryStream(stream);
   ASSERT_THAT(data, NotNull());
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 2U);
 
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 1U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
+  const auto& target_entries = data->GetTargetEntries();
+  ASSERT_EQ(target_entries.size(), 3U);
+  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, 0x01 /* Res_value::TYPE_REFERENCE */,
+                      0x7f020000);
+  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, 0x01 /* Res_value::TYPE_REFERENCE */,
+                      0x7f030000);
+  ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, 0x01 /* Res_value::TYPE_REFERENCE */,
+                      0x7f030001);
 
-  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03U);
-  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03U);
-  ASSERT_EQ(types[1]->GetEntryCount(), 3U);
-  ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
-  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
-  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
-  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
+  const auto& overlay_entries = data->GetOverlayEntries();
+  ASSERT_EQ(target_entries.size(), 3U);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x7f020000, 0x7f020000);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[1], 0x7f030000, 0x7f030000);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[2], 0x7f030001, 0x7f030002);
 }
 
 TEST(IdmapTests, CreateIdmapFromBinaryStream) {
@@ -130,34 +122,29 @@
 
   ASSERT_THAT(idmap->GetHeader(), NotNull());
   ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
-  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
+  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x02U);
   ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
   ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
-  ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), "target.apk");
-  ASSERT_EQ(idmap->GetHeader()->GetOverlayPath().to_string(), "overlay.apk");
+  ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), "targetX.apk");
+  ASSERT_EQ(idmap->GetHeader()->GetOverlayPath().to_string(), "overlayX.apk");
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
   ASSERT_EQ(dataBlocks.size(), 1U);
 
   const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 2U);
+  ASSERT_THAT(data, NotNull());
 
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 1U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
+  const auto& target_entries = data->GetTargetEntries();
+  ASSERT_EQ(target_entries.size(), 3U);
+  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, Res_value::TYPE_REFERENCE, 0x7f020000);
+  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, Res_value::TYPE_REFERENCE, 0x7f030000);
+  ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, Res_value::TYPE_REFERENCE, 0x7f030001);
 
-  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03U);
-  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03U);
-  ASSERT_EQ(types[1]->GetEntryCount(), 3U);
-  ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
-  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
-  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
-  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
+  const auto& overlay_entries = data->GetOverlayEntries();
+  ASSERT_EQ(target_entries.size(), 3U);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x7f020000, 0x7f020000);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[1], 0x7f030000, 0x7f030000);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[2], 0x7f030001, 0x7f030002);
 }
 
 TEST(IdmapTests, GracefullyFailToCreateIdmapFromCorruptBinaryStream) {
@@ -169,300 +156,140 @@
   ASSERT_FALSE(result);
 }
 
-void CreateIdmap(const StringPiece& target_apk_path, const StringPiece& overlay_apk_path,
-                 const PolicyBitmask& fulfilled_policies, bool enforce_overlayable,
-                 std::unique_ptr<const Idmap>* out_idmap) {
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path.to_string());
-  ASSERT_THAT(target_apk, NotNull());
-
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path.to_string());
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  auto result =
-      Idmap::FromApkAssets(*target_apk, *overlay_apk, fulfilled_policies, enforce_overlayable);
-  *out_idmap = result ? std::move(*result) : nullptr;
-}
-
-TEST(IdmapTests, CreateIdmapFromApkAssets) {
-  std::unique_ptr<const Idmap> idmap;
+TEST(IdmapTests, CreateIdmapHeaderFromApkAssets) {
   std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
   std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
-              /* enforce_overlayable */ true, &idmap);
+
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  ASSERT_THAT(target_apk, NotNull());
+
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  ASSERT_THAT(overlay_apk, NotNull());
+
+  auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
+                                           /* enforce_overlayable */ true);
+  ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
+  auto& idmap = *idmap_result;
+  ASSERT_THAT(idmap, NotNull());
 
   ASSERT_THAT(idmap->GetHeader(), NotNull());
   ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
-  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
+  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x02U);
   ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x76a20829);
   ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xc054fb26);
   ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
   ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
-  ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
-
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
-
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 2U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 1U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
-
-  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
-  ASSERT_EQ(types[1]->GetEntryCount(), 4U);
-  ASSERT_EQ(types[1]->GetEntryOffset(), 12U);
-  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
-  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
-  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
-  ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
 }
 
-// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
-  std::unique_ptr<const Idmap> idmap;
+Result<std::unique_ptr<const IdmapData>> TestIdmapDataFromApkAssets(
+    const android::StringPiece& local_target_apk_path,
+    const android::StringPiece& local_overlay_apk_path, const OverlayManifestInfo& overlay_info,
+    const PolicyBitmask& fulfilled_policies, bool enforce_overlayable) {
+  const std::string target_apk_path(GetTestDataPath() + local_target_apk_path.data());
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  if (!target_apk) {
+    return Error(R"(Failed to load target apk "%s")", target_apk_path.data());
+  }
+
+  const std::string overlay_apk_path(GetTestDataPath() + local_overlay_apk_path.data());
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  if (!overlay_apk) {
+    return Error(R"(Failed to load overlay apk "%s")", overlay_apk_path.data());
+  }
+
+  auto mapping = ResourceMapping::FromApkAssets(*target_apk, *overlay_apk, overlay_info,
+                                                fulfilled_policies, enforce_overlayable);
+
+  if (!mapping) {
+    return mapping.GetError();
+  }
+
+  return IdmapData::FromResourceMapping(*mapping);
+}
+
+TEST(IdmapTests, CreateIdmapDataFromApkAssets) {
   std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
-  std::string overlay_apk_path = GetTestDataPath() + "/system-overlay/system-overlay.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path,
-              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
-              /* enforce_overlayable */ true, &idmap);
+  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
+
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  ASSERT_THAT(target_apk, NotNull());
+
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  ASSERT_THAT(overlay_apk, NotNull());
+
+  auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
+                                           /* enforce_overlayable */ true);
+  ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
+  auto& idmap = *idmap_result;
   ASSERT_THAT(idmap, NotNull());
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
   ASSERT_EQ(dataBlocks.size(), 1U);
 
   const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+  ASSERT_THAT(data, NotNull());
 
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
+  const auto& target_entries = data->GetTargetEntries();
+  ASSERT_EQ(target_entries.size(), 4U);
+  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f010000, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f010000);
+  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020000);
+  ASSERT_TARGET_ENTRY(target_entries[2], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001);
+  ASSERT_TARGET_ENTRY(target_entries[3], 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020002);
 
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 1U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 4U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 8U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);   // string/policy_public
-  ASSERT_EQ(types[0]->GetEntry(1), kNoEntry);  // string/policy_signature
-  ASSERT_EQ(types[0]->GetEntry(2), 0x0001U);   // string/policy_system
-  ASSERT_EQ(types[0]->GetEntry(3), 0x0002U);   // string/policy_system_vendor
+  const auto& overlay_entries = data->GetOverlayEntries();
+  ASSERT_EQ(target_entries.size(), 4U);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x7f010000, 0x7f010000);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[1], 0x7f020000, 0x7f02000c);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[2], 0x7f020001, 0x7f02000e);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[3], 0x7f020002, 0x7f02000f);
 }
 
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignature) {
-  std::unique_ptr<const Idmap> idmap;
-  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
-  std::string overlay_apk_path = GetTestDataPath() + "/signature-overlay/signature-overlay.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path,
-              PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
+TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) {
+  OverlayManifestInfo info{};
+  info.target_package = "test.target";
+  info.target_name = "TestResources";
+  info.resource_mapping = 0x7f030001;  // xml/overlays_different_packages
+  auto idmap_data = TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk", info,
+                                               PolicyFlags::POLICY_PUBLIC,
+                                               /* enforce_overlayable */ false);
 
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
+  ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage();
+  auto& data = *idmap_data;
 
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+  const auto& target_entries = data->GetTargetEntries();
+  ASSERT_EQ(target_entries.size(), 2U);
+  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f02000c, Res_value::TYPE_REFERENCE,
+                      0x0104000a);  // string/str1 -> android:string/ok
+  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE,
+                      0x7f020001);  // string/str3 -> string/str4
 
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 1U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 1U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 9U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/policy_signature
+  const auto& overlay_entries = data->GetOverlayEntries();
+  ASSERT_EQ(overlay_entries.size(), 1U);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x7f020001, 0x7f02000e);  // string/str3 <- string/str4
 }
 
-// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
-  std::unique_ptr<const Idmap> idmap;
-  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
-  std::string overlay_apk_path =
-      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path,
-              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
+TEST(IdmapTests, CreateIdmapDataInlineResources) {
+  OverlayManifestInfo info{};
+  info.target_package = "test.target";
+  info.target_name = "TestResources";
+  info.resource_mapping = 0x7f030002;  // xml/overlays_inline
+  auto idmap_data = TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk", info,
+                                               PolicyFlags::POLICY_PUBLIC,
+                                               /* enforce_overlayable */ false);
 
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
+  ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage();
+  auto& data = *idmap_data;
 
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+  constexpr size_t overlay_string_pool_size = 8U;
+  const auto& target_entries = data->GetTargetEntries();
+  ASSERT_EQ(target_entries.size(), 2U);
+  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f010000, Res_value::TYPE_INT_DEC,
+                      73U);  // integer/int1 -> 73
+  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_STRING,
+                      overlay_string_pool_size + 0U);  // string/str1 -> "Hello World"
 
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 1U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 4U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 8U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0005U);   // string/policy_public
-  ASSERT_EQ(types[0]->GetEntry(1), kNoEntry);  // string/policy_signature
-  ASSERT_EQ(types[0]->GetEntry(2), 0x0007U);   // string/policy_system
-  ASSERT_EQ(types[0]->GetEntry(3), 0x0008U);   // string/policy_system_vendor
-}
-
-// Overlays should ignore all overlayable restrictions if enforcement of overlayable is disabled.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
-  std::unique_ptr<const Idmap> idmap;
-  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
-  std::string overlay_apk_path =
-      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path,
-              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
-              /* enforce_overlayable */ false, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
-
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 1U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 9U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/not_overlayable
-  ASSERT_EQ(types[0]->GetEntry(1), 0x0001U);  // string/policy_odm
-  ASSERT_EQ(types[0]->GetEntry(2), 0x0002U);  // string/policy_oem
-  ASSERT_EQ(types[0]->GetEntry(3), 0x0003U);  // string/other
-  ASSERT_EQ(types[0]->GetEntry(4), 0x0004U);  // string/policy_product
-  ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);  // string/policy_public
-  ASSERT_EQ(types[0]->GetEntry(6), 0x0006U);  // string/policy_signature
-  ASSERT_EQ(types[0]->GetEntry(7), 0x0007U);  // string/policy_system
-  ASSERT_EQ(types[0]->GetEntry(8), 0x0008U);  // string/policy_system_vendor
-}
-
-// Overlays that do not specify a target <overlayable> can overlay resources defined as overlayable.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
-  std::unique_ptr<const Idmap> idmap;
-  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
-  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
-              /* enforce_overlayable */ false, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
-
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 2U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 1U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/int1
-
-  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
-  ASSERT_EQ(types[1]->GetEntryCount(), 4U);
-  ASSERT_EQ(types[1]->GetEntryOffset(), 12U);
-  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);   // string/str1
-  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);  // string/str2
-  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);   // string/str3
-  ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);   // string/str4
-}
-
-// Overlays that are not pre-installed and are not signed with the same signature as the target
-// cannot overlay packages that have not defined overlayable resources.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPoliciesPublicFail) {
-  std::unique_ptr<const Idmap> idmap;
-  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
-  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, IsNull());
-}
-
-// Overlays that are pre-installed or are signed with the same signature as the target can overlay
-// packages that have not defined overlayable resources.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPolicies) {
-  std::unique_ptr<const Idmap> idmap;
-  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
-  std::string overlay_apk_path =
-      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
-
-  auto CheckEntries = [&]() -> void {
-    const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-    ASSERT_EQ(dataBlocks.size(), 1U);
-
-    const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-    ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-    ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
-
-    const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-    ASSERT_EQ(types.size(), 1U);
-
-    ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-    ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-    ASSERT_EQ(types[0]->GetEntryCount(), 9U);
-    ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
-    ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/not_overlayable
-    ASSERT_EQ(types[0]->GetEntry(1), 0x0001U);  // string/policy_odm
-    ASSERT_EQ(types[0]->GetEntry(2), 0x0002U);  // string/policy_oem
-    ASSERT_EQ(types[0]->GetEntry(3), 0x0003U);  // string/other
-    ASSERT_EQ(types[0]->GetEntry(4), 0x0004U);  // string/policy_product
-    ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);  // string/policy_public
-    ASSERT_EQ(types[0]->GetEntry(6), 0x0006U);  // string/policy_signature
-    ASSERT_EQ(types[0]->GetEntry(7), 0x0007U);  // string/policy_system
-    ASSERT_EQ(types[0]->GetEntry(8), 0x0008U);  // string/policy_system_vendor
-  };
-
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SIGNATURE,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-  CheckEntries();
-
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PRODUCT_PARTITION,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-  CheckEntries();
-
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SYSTEM_PARTITION,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-  CheckEntries();
-
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_VENDOR_PARTITION,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-  CheckEntries();
-
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_ODM_PARTITION,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-  CheckEntries();
-
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_OEM_PARTITION,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-  CheckEntries();
+  const auto& overlay_entries = data->GetOverlayEntries();
+  ASSERT_EQ(overlay_entries.size(), 0U);
 }
 
 TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
@@ -602,10 +429,6 @@
     stream_ << "TestVisitor::visit(IdmapData::Header)" << std::endl;
   }
 
-  void visit(const IdmapData::TypeEntry& idmap ATTRIBUTE_UNUSED) override {
-    stream_ << "TestVisitor::visit(IdmapData::TypeEntry)" << std::endl;
-  }
-
  private:
   std::ostream& stream_;
 };
@@ -622,12 +445,10 @@
   (*idmap)->accept(&visitor);
 
   ASSERT_EQ(test_stream.str(),
-            "TestVisitor::visit(Idmap)\n"
             "TestVisitor::visit(IdmapHeader)\n"
-            "TestVisitor::visit(IdmapData)\n"
+            "TestVisitor::visit(Idmap)\n"
             "TestVisitor::visit(IdmapData::Header)\n"
-            "TestVisitor::visit(IdmapData::TypeEntry)\n"
-            "TestVisitor::visit(IdmapData::TypeEntry)\n");
+            "TestVisitor::visit(IdmapData)\n");
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index c243d74..d387880 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -47,11 +47,21 @@
   (*idmap)->accept(&visitor);
 
   ASSERT_NE(stream.str().find("00000000: 504d4449  magic\n"), std::string::npos);
-  ASSERT_NE(stream.str().find("00000004: 00000001  version\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000004: 00000002  version\n"), std::string::npos);
   ASSERT_NE(stream.str().find("00000008: 76a20829  target crc\n"), std::string::npos);
   ASSERT_NE(stream.str().find("0000000c: c054fb26  overlay crc\n"), std::string::npos);
-  ASSERT_NE(stream.str().find("0000021c: 00000000  0x7f010000 -> 0x7f010000 integer/int1\n"),
+  ASSERT_NE(stream.str().find("00000210:       7f  target package id\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000211:       7f  overlay package id\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000212: 00000004  target entry count\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000216: 00000004  overlay entry count\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000021a: 00000008  string pool index offset\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000021e: 000000b4  string pool byte length\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000222: 7f010000  target id: integer/int1\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000226:       07  type: reference (dynamic)\n"),
             std::string::npos);
+  ASSERT_NE(stream.str().find("00000227: 7f010000  value: integer/int1\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000246: 7f010000  overlay id: integer/int1\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000024a: 7f010000  target id: integer/int1\n"), std::string::npos);
 }
 
 TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
@@ -68,10 +78,21 @@
   (*idmap)->accept(&visitor);
 
   ASSERT_NE(stream.str().find("00000000: 504d4449  magic\n"), std::string::npos);
-  ASSERT_NE(stream.str().find("00000004: 00000001  version\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000004: 00000002  version\n"), std::string::npos);
   ASSERT_NE(stream.str().find("00000008: 00001234  target crc\n"), std::string::npos);
   ASSERT_NE(stream.str().find("0000000c: 00005678  overlay crc\n"), std::string::npos);
-  ASSERT_NE(stream.str().find("0000021c: 00000000  0x7f020000 -> 0x7f020000\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000210:       7f  target package id\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000211:       7f  overlay package id\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000212: 00000003  target entry count\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000216: 00000003  overlay entry count\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000021a: 00000000  string pool index offset\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000021e: 00000000  string pool byte length\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000222: 7f020000  target id\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000226:       01  type: reference\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000227: 7f020000  value\n"), std::string::npos);
+
+  ASSERT_NE(stream.str().find("0000023d: 7f020000  overlay id\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000241: 7f020000  target id\n"), std::string::npos);
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp
index 1ef41de..64304f6 100644
--- a/cmds/idmap2/tests/ResourceMappingTests.cpp
+++ b/cmds/idmap2/tests/ResourceMappingTests.cpp
@@ -27,6 +27,7 @@
 #include "gtest/gtest.h"
 #include "idmap2/ResourceMapping.h"
 
+using android::Res_value;
 using android::idmap2::utils::ExtractOverlayManifestInfo;
 
 namespace android::idmap2 {
@@ -109,14 +110,14 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
-  ASSERT_RESULT(MappingExists(res, 0x7f010000, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010000,
-                              true /* rewrite */));  // integer/int1
-  ASSERT_RESULT(MappingExists(res, 0x7f02000c, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020000,
-                              true /* rewrite */));  // string/str1
-  ASSERT_RESULT(MappingExists(res, 0x7f02000e, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020001,
-                              true /* rewrite */));  // string/str3
-  ASSERT_RESULT(MappingExists(res, 0x7f02000f, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020002,
-                              true /* rewrite */));  // string/str4
+  ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_REFERENCE, 0x7f010000,
+                              false /* rewrite */));  // integer/int1
+  ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x7f020000,
+                              false /* rewrite */));  // string/str1
+  ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_REFERENCE, 0x7f020001,
+                              false /* rewrite */));  // string/str3
+  ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_REFERENCE, 0x7f020002,
+                              false /* rewrite */));  // string/str4
 }
 
 TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) {
@@ -131,15 +132,15 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
-  ASSERT_RESULT(MappingExists(res, 0x7f02000c, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020002,
+  ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020002,
                               true /* rewrite */));  // string/str1 -> string/str4
-  ASSERT_RESULT(MappingExists(res, 0x7f02000e, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020000,
+  ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020000,
                               true /* rewrite */));  // string/str3 -> string/str1
-  ASSERT_RESULT(MappingExists(res, 0x7f02000f, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020001,
+  ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001,
                               true /* rewrite */));  // string/str4 -> string/str3
 }
 
-TEST(ResourceMappingTests, DoNotRewriteNonResourceMapping) {
+TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) {
   OverlayManifestInfo info{};
   info.target_package = "test.target";
   info.target_name = "TestResources";
@@ -152,9 +153,9 @@
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
   ASSERT_EQ(res.GetOverlayToTargetMap().size(), 1U);
-  ASSERT_RESULT(MappingExists(res, 0x7f02000c, 0x01 /* Res_value::TYPE_REFERENCE */, 0x0104000a,
+  ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x0104000a,
                               false /* rewrite */));  // string/str1 -> android:string/ok
-  ASSERT_RESULT(MappingExists(res, 0x7f02000e, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020001,
+  ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001,
                               true /* rewrite */));  // string/str3 -> string/str4
 }
 
@@ -172,10 +173,10 @@
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
   ASSERT_EQ(res.GetOverlayToTargetMap().size(), 0U);
-  ASSERT_RESULT(MappingExists(res, 0x7f02000c, 0x03 /* Res_value::TYPE_STRING */,
+  ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_STRING,
                               overlay_string_pool_size + 0U,
                               false /* rewrite */));  // string/str1 -> "Hello World"
-  ASSERT_RESULT(MappingExists(res, 0x7f010000, 0x10 /* Res_value::TYPE_INT_DEC */, 73U,
+  ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_INT_DEC, 73U,
                               false /* rewrite */));  // string/str1 -> "Hello World"
 }
 
@@ -188,12 +189,12 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
-  ASSERT_RESULT(MappingExists(res, 0x7f020008, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010000,
-                              true /* rewrite */));  // string/policy_public
-  ASSERT_RESULT(MappingExists(res, 0x7f02000a, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010001,
-                              true /* rewrite */));  // string/policy_system
-  ASSERT_RESULT(MappingExists(res, 0x7f02000b, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010002,
-                              true /* rewrite */));  // string/policy_system_vendor
+  ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010000,
+                              false /* rewrite */));  // string/policy_public
+  ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010001,
+                              false /* rewrite */));  // string/policy_system
+  ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010002,
+                              false /* rewrite */));  // string/policy_system_vendor
 }
 
 // Resources that are not declared as overlayable and resources that a protected by policies the
@@ -207,12 +208,12 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
-  ASSERT_RESULT(MappingExists(res, 0x7f020008, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010005,
-                              true /* rewrite */));  // string/policy_public
-  ASSERT_RESULT(MappingExists(res, 0x7f02000a, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010007,
-                              true /* rewrite */));  // string/policy_system
-  ASSERT_RESULT(MappingExists(res, 0x7f02000b, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010008,
-                              true /* rewrite */));  // string/policy_system_vendor
+  ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005,
+                              false /* rewrite */));  // string/policy_public
+  ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007,
+                              false /* rewrite */));  // string/policy_system
+  ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008,
+                              false /* rewrite */));  // string/policy_system_vendor
 }
 
 // Resources that are not declared as overlayable and resources that a protected by policies the
@@ -227,24 +228,24 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 9U);
-  ASSERT_RESULT(MappingExists(res, 0x7f020003, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010000,
-                              true /* rewrite */));  // string/not_overlayable
-  ASSERT_RESULT(MappingExists(res, 0x7f020004, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010001,
-                              true /* rewrite */));  // string/other
-  ASSERT_RESULT(MappingExists(res, 0x7f020005, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010002,
-                              true /* rewrite */));  // string/policy_odm
-  ASSERT_RESULT(MappingExists(res, 0x7f020006, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010003,
-                              true /* rewrite */));  // string/policy_oem
-  ASSERT_RESULT(MappingExists(res, 0x7f020007, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010004,
-                              true /* rewrite */));  // string/policy_product
-  ASSERT_RESULT(MappingExists(res, 0x7f020008, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010005,
-                              true /* rewrite */));  // string/policy_public
-  ASSERT_RESULT(MappingExists(res, 0x7f020009, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010006,
-                              true /* rewrite */));  // string/policy_signature
-  ASSERT_RESULT(MappingExists(res, 0x7f02000a, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010007,
-                              true /* rewrite */));  // string/policy_system
-  ASSERT_RESULT(MappingExists(res, 0x7f02000b, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010008,
-                              true /* rewrite */));  // string/policy_system_vendor
+  ASSERT_RESULT(MappingExists(res, 0x7f020003, Res_value::TYPE_REFERENCE, 0x7f010000,
+                              false /* rewrite */));  // string/not_overlayable
+  ASSERT_RESULT(MappingExists(res, 0x7f020004, Res_value::TYPE_REFERENCE, 0x7f010001,
+                              false /* rewrite */));  // string/other
+  ASSERT_RESULT(MappingExists(res, 0x7f020005, Res_value::TYPE_REFERENCE, 0x7f010002,
+                              false /* rewrite */));  // string/policy_odm
+  ASSERT_RESULT(MappingExists(res, 0x7f020006, Res_value::TYPE_REFERENCE, 0x7f010003,
+                              false /* rewrite */));  // string/policy_oem
+  ASSERT_RESULT(MappingExists(res, 0x7f020007, Res_value::TYPE_REFERENCE, 0x7f010004,
+                              false /* rewrite */));  // string/policy_product
+  ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005,
+                              false /* rewrite */));  // string/policy_public
+  ASSERT_RESULT(MappingExists(res, 0x7f020009, Res_value::TYPE_REFERENCE, 0x7f010006,
+                              false /* rewrite */));  // string/policy_signature
+  ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007,
+                              false /* rewrite */));  // string/policy_system
+  ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008,
+                              false /* rewrite */));  // string/policy_system_vendor
 }
 
 // Overlays that do not target an <overlayable> tag can overlay resources defined within any
@@ -257,14 +258,14 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
-  ASSERT_RESULT(MappingExists(res, 0x7f010000, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010000,
-                              true /* rewrite */));  // integer/int1
-  ASSERT_RESULT(MappingExists(res, 0x7f02000c, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020000,
-                              true /* rewrite */));  // string/str1
-  ASSERT_RESULT(MappingExists(res, 0x7f02000e, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020001,
-                              true /* rewrite */));  // string/str3
-  ASSERT_RESULT(MappingExists(res, 0x7f02000f, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020002,
-                              true /* rewrite */));  // string/str4
+  ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_REFERENCE, 0x7f010000,
+                              false /* rewrite */));  // integer/int1
+  ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x7f020000,
+                              false /* rewrite */));  // string/str1
+  ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_REFERENCE, 0x7f020001,
+                              false /* rewrite */));  // string/str3
+  ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_REFERENCE, 0x7f020002,
+                              false /* rewrite */));  // string/str4
 }
 
 // Overlays that are neither pre-installed nor signed with the same signature as the target cannot
@@ -291,24 +292,24 @@
     ASSERT_TRUE(resources) << resources.GetErrorMessage();
     auto& res = *resources;
     ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 9U);
-    ASSERT_RESULT(MappingExists(res, 0x7f020003, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010000,
-                                true /* rewrite */));  // string/not_overlayable
-    ASSERT_RESULT(MappingExists(res, 0x7f020004, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010001,
-                                true /* rewrite */));  // string/other
-    ASSERT_RESULT(MappingExists(res, 0x7f020005, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010002,
-                                true /* rewrite */));  // string/policy_odm
-    ASSERT_RESULT(MappingExists(res, 0x7f020006, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010003,
-                                true /* rewrite */));  // string/policy_oem
-    ASSERT_RESULT(MappingExists(res, 0x7f020007, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010004,
-                                true /* rewrite */));  // string/policy_product
-    ASSERT_RESULT(MappingExists(res, 0x7f020008, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010005,
-                                true /* rewrite */));  // string/policy_public
-    ASSERT_RESULT(MappingExists(res, 0x7f020009, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010006,
-                                true /* rewrite */));  // string/policy_signature
-    ASSERT_RESULT(MappingExists(res, 0x7f02000a, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010007,
-                                true /* rewrite */));  // string/policy_system
-    ASSERT_RESULT(MappingExists(res, 0x7f02000b, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010008,
-                                true /* rewrite */));  // string/policy_system_vendor
+    ASSERT_RESULT(MappingExists(res, 0x7f020003, Res_value::TYPE_REFERENCE, 0x7f010000,
+                                false /* rewrite */));  // string/not_overlayable
+    ASSERT_RESULT(MappingExists(res, 0x7f020004, Res_value::TYPE_REFERENCE, 0x7f010001,
+                                false /* rewrite */));  // string/other
+    ASSERT_RESULT(MappingExists(res, 0x7f020005, Res_value::TYPE_REFERENCE, 0x7f010002,
+                                false /* rewrite */));  // string/policy_odm
+    ASSERT_RESULT(MappingExists(res, 0x7f020006, Res_value::TYPE_REFERENCE, 0x7f010003,
+                                false /* rewrite */));  // string/policy_oem
+    ASSERT_RESULT(MappingExists(res, 0x7f020007, Res_value::TYPE_REFERENCE, 0x7f010004,
+                                false /* rewrite */));  // string/policy_product
+    ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005,
+                                false /* rewrite */));  // string/policy_public
+    ASSERT_RESULT(MappingExists(res, 0x7f020009, Res_value::TYPE_REFERENCE, 0x7f010006,
+                                false /* rewrite */));  // string/policy_signature
+    ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007,
+                                false /* rewrite */));  // string/policy_system
+    ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008,
+                                false /* rewrite */));  // string/policy_system_vendor
   };
 
   CheckEntries(PolicyFlags::POLICY_SIGNATURE);
diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h
index a7c2f28..8868b53 100644
--- a/cmds/idmap2/tests/TestHelpers.h
+++ b/cmds/idmap2/tests/TestHelpers.h
@@ -30,7 +30,7 @@
     0x49, 0x44, 0x4d, 0x50,
 
     // 0x4: version
-    0x01, 0x00, 0x00, 0x00,
+    0x02, 0x00, 0x00, 0x00,
 
     // 0x8: target crc
     0x34, 0x12, 0x00, 0x00,
@@ -38,8 +38,8 @@
     // 0xc: overlay crc
     0x78, 0x56, 0x00, 0x00,
 
-    // 0x10: target path "target.apk"
-    0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    // 0x10: target path "targetX.apk"
+    0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -56,8 +56,8 @@
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
-    // 0x110: overlay path "overlay.apk"
-    0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00,
+    // 0x110: overlay path "overlayX.apk"
+    0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -75,49 +75,63 @@
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
     // DATA HEADER
-    // 0x210: target package id
-    0x7f, 0x00,
+    // 0x210: target_package_id
+    0x7f,
 
-    // 0x212: types count
-    0x02, 0x00,
+    // 0x211: overlay_package_id
+    0x7f,
 
-    // DATA BLOCK
-    // 0x214: target type
-    0x02, 0x00,
+    // 0x212: target_entry_count
+    0x03, 0x00, 0x00, 0x00,
 
-    // 0x216: overlay type
-    0x02, 0x00,
+    // 0x216: overlay_entry_count
+    0x03, 0x00, 0x00, 0x00,
 
-    // 0x218: entry count
-    0x01, 0x00,
-
-    // 0x21a: entry offset
-    0x00, 0x00,
-
-    // 0x21c: entries
+    // 0x21a: string_pool_offset
     0x00, 0x00, 0x00, 0x00,
 
-    // DATA BLOCK
-    // 0x220: target type
-    0x03, 0x00,
-
-    // 0x222: overlay type
-    0x03, 0x00,
-
-    // 0x224: entry count
-    0x03, 0x00,
-
-    // 0x226: entry offset
-    0x03, 0x00,
-
-    // 0x228, 0x22c, 0x230: entries
+    // 0x21e: string_pool_byte_length
     0x00, 0x00, 0x00, 0x00,
 
-    0xff, 0xff, 0xff, 0xff,
+    // TARGET ENTRIES
+    // 0x222: 0x7f020000
+    0x00, 0x00, 0x02, 0x7f,
 
-    0x01, 0x00, 0x00, 0x00};
+    // 0x226: TYPE_REFERENCE
+    0x01,
 
-const unsigned int idmap_raw_data_len = 565;
+    // 0x227: 0x7f020000
+    0x00, 0x00, 0x02, 0x7f,
+
+    // 0x22b: 0x7f030000
+    0x00, 0x00, 0x03, 0x7f,
+
+    // 0x22f: TYPE_REFERENCE
+    0x01,
+
+    // 0x230: 0x7f030000
+    0x00, 0x00, 0x03, 0x7f,
+
+    // 0x234: 0x7f030002
+    0x02, 0x00, 0x03, 0x7f,
+
+    // 0x238: TYPE_REFERENCE
+    0x01,
+
+    // 0x239: 0x7f030001
+    0x01, 0x00, 0x03, 0x7f,
+
+    // OVERLAY ENTRIES
+    // 0x23d: 0x7f020000 -> 0x7f020000
+    0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f,
+
+    // 0x245: 0x7f030000 -> 0x7f030000
+    0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x03, 0x7f,
+
+    // 0x24d: 0x7f030001 -> 0x7f030002
+    0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f};
+
+const unsigned int idmap_raw_data_len = 0x255;
 
 std::string GetTestDataPath();
 
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index cb27325..8af925a 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -230,6 +230,7 @@
         "tests/e2e/Anomaly_duration_sum_e2e_test.cpp",
         "tests/e2e/Attribution_e2e_test.cpp",
         "tests/e2e/ConfigTtl_e2e_test.cpp",
+        "tests/e2e/CountMetric_e2e_test.cpp",
         "tests/e2e/DurationMetric_e2e_test.cpp",
         "tests/e2e/GaugeMetric_e2e_pull_test.cpp",
         "tests/e2e/GaugeMetric_e2e_push_test.cpp",
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index ff7416c..6c3dff2 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -16,24 +16,26 @@
 
 #define DEBUG false  // STOPSHIP if true
 #include "Log.h"
-#include "statslog.h"
+
+#include "StatsLogProcessor.h"
 
 #include <android-base/file.h>
 #include <dirent.h>
 #include <frameworks/base/cmds/statsd/src/active_config_list.pb.h>
-#include "StatsLogProcessor.h"
+#include <log/log_event_list.h>
+#include <utils/Errors.h>
+#include <utils/SystemClock.h>
+
 #include "android-base/stringprintf.h"
 #include "external/StatsPullerManager.h"
 #include "guardrail/StatsdStats.h"
 #include "metrics/CountMetricProducer.h"
+#include "state/StateManager.h"
 #include "stats_log_util.h"
 #include "stats_util.h"
+#include "statslog.h"
 #include "storage/StorageManager.h"
 
-#include <log/log_event_list.h>
-#include <utils/Errors.h>
-#include <utils/SystemClock.h>
-
 using namespace android;
 using android::base::StringPrintf;
 using android::util::FIELD_COUNT_REPEATED;
@@ -218,6 +220,8 @@
         onIsolatedUidChangedEventLocked(*event);
     }
 
+    StateManager::getInstance().onLogEvent(*event);
+
     if (mMetricsManagers.empty()) {
         return;
     }
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 3d002d2..8292a3a 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -262,6 +262,10 @@
     FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithSameDeactivation);
     FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations);
 
+    FRIEND_TEST(CountMetricE2eTest, TestWithSimpleState);
+    FRIEND_TEST(CountMetricE2eTest, TestWithMappedState);
+    FRIEND_TEST(CountMetricE2eTest, TestWithMultipleStates);
+
     FRIEND_TEST(DurationMetricE2eTest, TestOneBucket);
     FRIEND_TEST(DurationMetricE2eTest, TestTwoBuckets);
     FRIEND_TEST(DurationMetricE2eTest, TestWithActivation);
diff --git a/cmds/statsd/src/anomaly/subscriber_util.cpp b/cmds/statsd/src/anomaly/subscriber_util.cpp
index e09d575..4c30c4c 100644
--- a/cmds/statsd/src/anomaly/subscriber_util.cpp
+++ b/cmds/statsd/src/anomaly/subscriber_util.cpp
@@ -40,7 +40,7 @@
 
     for (const Subscription& subscription : subscriptions) {
         if (subscription.probability_of_informing() < 1
-                && ((float)rand() / RAND_MAX) >= subscription.probability_of_informing()) {
+                && ((float)rand() / (float)RAND_MAX) >= subscription.probability_of_informing()) {
             // Note that due to float imprecision, 0.0 and 1.0 might not truly mean never/always.
             // The config writer was advised to use -0.1 and 1.1 for never/always.
             ALOGI("Fate decided that a subscriber would not be informed.");
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 6249de3..8618d4d 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -5760,6 +5760,8 @@
         AUTO_DENIED = 8;
         // permission request was ignored because permission is restricted
         IGNORED_RESTRICTED_PERMISSION = 9;
+        // one time permission was granted by user action
+        USER_GRANTED_ONE_TIME = 10;
     }
     // The result of the permission grant
     optional Result result = 6;
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index b5c8e35..4a06387 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -18,13 +18,15 @@
 #include "Log.h"
 
 #include "CountMetricProducer.h"
-#include "guardrail/StatsdStats.h"
-#include "stats_util.h"
-#include "stats_log_util.h"
 
+#include <inttypes.h>
 #include <limits.h>
 #include <stdlib.h>
 
+#include "guardrail/StatsdStats.h"
+#include "stats_log_util.h"
+#include "stats_util.h"
+
 using android::util::FIELD_COUNT_REPEATED;
 using android::util::FIELD_TYPE_BOOL;
 using android::util::FIELD_TYPE_FLOAT;
@@ -65,16 +67,16 @@
 const int FIELD_ID_START_BUCKET_ELAPSED_MILLIS = 5;
 const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6;
 
-CountMetricProducer::CountMetricProducer(const ConfigKey& key, const CountMetric& metric,
-                                         const int conditionIndex,
-                                         const sp<ConditionWizard>& wizard,
-                                         const int64_t timeBaseNs, const int64_t startTimeNs,
-                                         const unordered_map<int, shared_ptr<Activation>>&
-                                                 eventActivationMap,
-                                         const unordered_map<int, vector<shared_ptr<Activation>>>&
-                                                 eventDeactivationMap)
+CountMetricProducer::CountMetricProducer(
+        const ConfigKey& key, const CountMetric& metric, const int conditionIndex,
+        const sp<ConditionWizard>& wizard, const int64_t timeBaseNs, const int64_t startTimeNs,
+
+        const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
+        const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
+        const vector<int>& slicedStateAtoms,
+        const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
     : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap,
-                     eventDeactivationMap) {
+                     eventDeactivationMap, slicedStateAtoms, stateGroupMap) {
     if (metric.has_bucket()) {
         mBucketSizeNs =
                 TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket()) * 1000000;
@@ -100,6 +102,8 @@
         mConditionSliced = true;
     }
 
+    // TODO(tsaichristine): b/142124705 handle metric state links
+
     flushIfNeededLocked(startTimeNs);
     // Adjust start for partial bucket
     mCurrentBucketStartTimeNs = startTimeNs;
@@ -112,6 +116,12 @@
     VLOG("~CountMetricProducer() called");
 }
 
+void CountMetricProducer::onStateChanged(int atomId, const HashableDimensionKey& primaryKey,
+                                         int oldState, int newState) {
+    VLOG("CountMetric %lld onStateChanged State%d, key %s, %d -> %d", (long long)mMetricId, atomId,
+         primaryKey.toString().c_str(), oldState, newState);
+}
+
 void CountMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
     if (mCurrentSlicedCounter == nullptr ||
         mCurrentSlicedCounter->size() == 0) {
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 61913c7..61e0892 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -17,15 +17,16 @@
 #ifndef COUNT_METRIC_PRODUCER_H
 #define COUNT_METRIC_PRODUCER_H
 
-#include <unordered_map>
-
 #include <android/util/ProtoOutputStream.h>
 #include <gtest/gtest_prod.h>
-#include "../anomaly/AnomalyTracker.h"
-#include "../condition/ConditionTracker.h"
-#include "../matchers/matcher_util.h"
+
+#include <unordered_map>
+
 #include "MetricProducer.h"
+#include "anomaly/AnomalyTracker.h"
+#include "condition/ConditionTracker.h"
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "matchers/matcher_util.h"
 #include "stats_util.h"
 
 namespace android {
@@ -40,16 +41,20 @@
 
 class CountMetricProducer : public MetricProducer {
 public:
-    CountMetricProducer(const ConfigKey& key, const CountMetric& countMetric,
-                        const int conditionIndex, const sp<ConditionWizard>& wizard,
-                        const int64_t timeBaseNs, const int64_t startTimeNs,
-                        const std::unordered_map<int, std::shared_ptr<Activation>>&
-                                eventActivationMap = {},
-                        const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
-                                eventDeactivationMap = {});
+    CountMetricProducer(
+            const ConfigKey& key, const CountMetric& countMetric, const int conditionIndex,
+            const sp<ConditionWizard>& wizard, const int64_t timeBaseNs, const int64_t startTimeNs,
+            const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
+            const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
+                    eventDeactivationMap = {},
+            const vector<int>& slicedStateAtoms = {},
+            const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap = {});
 
     virtual ~CountMetricProducer();
 
+    void onStateChanged(int atomId, const HashableDimensionKey& primaryKey, int oldState,
+                        int newState) override;
+
 protected:
     void onMatchedLogEventInternalLocked(
             const size_t matcherIndex, const MetricDimensionKey& eventKey,
@@ -106,6 +111,7 @@
     FRIEND_TEST(CountMetricProducerTest, TestEventWithAppUpgrade);
     FRIEND_TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket);
     FRIEND_TEST(CountMetricProducerTest, TestFirstBucket);
+    FRIEND_TEST(CountMetricProducerTest, TestOneWeekTimeUnit);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 31b90f3..ab2a1c3 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -69,9 +69,11 @@
         const bool nesting, const sp<ConditionWizard>& wizard,
         const FieldMatcher& internalDimensions, const int64_t timeBaseNs, const int64_t startTimeNs,
         const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
-        const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap)
+        const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
+        const vector<int>& slicedStateAtoms,
+        const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
     : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap,
-                     eventDeactivationMap),
+                     eventDeactivationMap, slicedStateAtoms, stateGroupMap),
       mAggregationType(metric.aggregation_type()),
       mStartIndex(startIndex),
       mStopIndex(stopIndex),
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 0592b18..7457d7f 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -38,16 +38,16 @@
 
 class DurationMetricProducer : public MetricProducer {
 public:
-    DurationMetricProducer(const ConfigKey& key, const DurationMetric& durationMetric,
-                           const int conditionIndex, const size_t startIndex,
-                           const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
-                           const sp<ConditionWizard>& wizard,
-                           const FieldMatcher& internalDimensions, const int64_t timeBaseNs,
-                           const int64_t startTimeNs,
-                           const unordered_map<int, shared_ptr<Activation>>&
-                                   eventActivationMap = {},
-                           const unordered_map<int, vector<shared_ptr<Activation>>>&
-                                   eventDeactivationMap = {});
+    DurationMetricProducer(
+            const ConfigKey& key, const DurationMetric& durationMetric, const int conditionIndex,
+            const size_t startIndex, const size_t stopIndex, const size_t stopAllIndex,
+            const bool nesting, const sp<ConditionWizard>& wizard,
+            const FieldMatcher& internalDimensions, const int64_t timeBaseNs,
+            const int64_t startTimeNs,
+            const unordered_map<int, shared_ptr<Activation>>& eventActivationMap = {},
+            const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap = {},
+            const vector<int>& slicedStateAtoms = {},
+            const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap = {});
 
     virtual ~DurationMetricProducer();
 
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index a60a916..32eb077 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -52,16 +52,15 @@
 const int FIELD_ID_ELAPSED_TIMESTAMP_NANOS = 1;
 const int FIELD_ID_ATOMS = 2;
 
-EventMetricProducer::EventMetricProducer(const ConfigKey& key, const EventMetric& metric,
-                                         const int conditionIndex,
-                                         const sp<ConditionWizard>& wizard,
-                                         const int64_t startTimeNs,
-                                         const unordered_map<int, shared_ptr<Activation>>&
-                                                 eventActivationMap,
-                                         const unordered_map<int, vector<shared_ptr<Activation>>>&
-                                                 eventDeactivationMap)
+EventMetricProducer::EventMetricProducer(
+        const ConfigKey& key, const EventMetric& metric, const int conditionIndex,
+        const sp<ConditionWizard>& wizard, const int64_t startTimeNs,
+        const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
+        const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
+        const vector<int>& slicedStateAtoms,
+        const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
     : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard, eventActivationMap,
-                     eventDeactivationMap) {
+                     eventDeactivationMap, slicedStateAtoms, stateGroupMap) {
     if (metric.links().size() > 0) {
         for (const auto& link : metric.links()) {
             Metric2Condition mc;
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index aab53c8..dca37e8 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -33,13 +33,14 @@
 
 class EventMetricProducer : public MetricProducer {
 public:
-    EventMetricProducer(const ConfigKey& key, const EventMetric& eventMetric,
-                        const int conditionIndex, const sp<ConditionWizard>& wizard,
-                        const int64_t startTimeNs,
-                        const std::unordered_map<int, std::shared_ptr<Activation>>&
-                                eventActivationMap = {},
-                        const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
-                                eventDeactivationMap = {});
+    EventMetricProducer(
+            const ConfigKey& key, const EventMetric& eventMetric, const int conditionIndex,
+            const sp<ConditionWizard>& wizard, const int64_t startTimeNs,
+            const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
+            const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
+                    eventDeactivationMap = {},
+            const vector<int>& slicedStateAtoms = {},
+            const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap = {});
 
     virtual ~EventMetricProducer();
 
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index e409b6fb..d0f88a8 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -74,9 +74,11 @@
         const int atomId, const int64_t timeBaseNs, const int64_t startTimeNs,
         const sp<StatsPullerManager>& pullerManager,
         const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
-        const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap)
+        const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
+        const vector<int>& slicedStateAtoms,
+        const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
     : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap,
-            eventDeactivationMap),
+                     eventDeactivationMap, slicedStateAtoms, stateGroupMap),
       mWhatMatcherIndex(whatMatcherIndex),
       mEventMatcherWizard(matcherWizard),
       mPullerManager(pullerManager),
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index dfe1d56..640a02a 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -56,16 +56,17 @@
 // producer always reports the guage at the earliest time of the bucket when the condition is met.
 class GaugeMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
 public:
-    GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric,
-                        const int conditionIndex, const sp<ConditionWizard>& conditionWizard,
-                        const int whatMatcherIndex,const sp<EventMatcherWizard>& matcherWizard,
-                        const int pullTagId, const int triggerAtomId, const int atomId,
-                        const int64_t timeBaseNs, const int64_t startTimeNs,
-                        const sp<StatsPullerManager>& pullerManager,
-                        const std::unordered_map<int, std::shared_ptr<Activation>>&
-                                eventActivationMap = {},
-                        const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
-                                eventDeactivationMap = {});
+    GaugeMetricProducer(
+            const ConfigKey& key, const GaugeMetric& gaugeMetric, const int conditionIndex,
+            const sp<ConditionWizard>& conditionWizard, const int whatMatcherIndex,
+            const sp<EventMatcherWizard>& matcherWizard, const int pullTagId,
+            const int triggerAtomId, const int atomId, const int64_t timeBaseNs,
+            const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager,
+            const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
+            const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
+                    eventDeactivationMap = {},
+            const vector<int>& slicedStateAtoms = {},
+            const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap = {});
 
     virtual ~GaugeMetricProducer();
 
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 3426a19..2a700ef 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -45,23 +45,27 @@
         const int conditionIndex, const sp<ConditionWizard>& wizard,
         const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap,
         const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
-                eventDeactivationMap)
-        : mMetricId(metricId),
-          mConfigKey(key),
-          mTimeBaseNs(timeBaseNs),
-          mCurrentBucketStartTimeNs(timeBaseNs),
-          mCurrentBucketNum(0),
-          mCondition(initialCondition(conditionIndex)),
-          mConditionTrackerIndex(conditionIndex),
-          mConditionSliced(false),
-          mWizard(wizard),
-          mContainANYPositionInDimensionsInWhat(false),
-          mSliceByPositionALL(false),
-          mHasLinksToAllConditionDimensionsInTracker(false),
-          mEventActivationMap(eventActivationMap),
-          mEventDeactivationMap(eventDeactivationMap),
-          mIsActive(mEventActivationMap.empty()) {
-    }
+                eventDeactivationMap,
+        const vector<int>& slicedStateAtoms,
+        const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
+    : mMetricId(metricId),
+      mConfigKey(key),
+      mTimeBaseNs(timeBaseNs),
+      mCurrentBucketStartTimeNs(timeBaseNs),
+      mCurrentBucketNum(0),
+      mCondition(initialCondition(conditionIndex)),
+      mConditionTrackerIndex(conditionIndex),
+      mConditionSliced(false),
+      mWizard(wizard),
+      mContainANYPositionInDimensionsInWhat(false),
+      mSliceByPositionALL(false),
+      mHasLinksToAllConditionDimensionsInTracker(false),
+      mEventActivationMap(eventActivationMap),
+      mEventDeactivationMap(eventDeactivationMap),
+      mIsActive(mEventActivationMap.empty()),
+      mSlicedStateAtoms(slicedStateAtoms),
+      mStateGroupMap(stateGroupMap) {
+}
 
 void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) {
     if (!mIsActive) {
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 1e1eb69..a72de22 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -17,19 +17,19 @@
 #ifndef METRIC_PRODUCER_H
 #define METRIC_PRODUCER_H
 
-#include <shared_mutex>
-
 #include <frameworks/base/cmds/statsd/src/active_config_list.pb.h>
+#include <log/logprint.h>
+#include <utils/RefBase.h>
+
+#include <unordered_map>
+
 #include "HashableDimensionKey.h"
 #include "anomaly/AnomalyTracker.h"
 #include "condition/ConditionWizard.h"
 #include "config/ConfigKey.h"
 #include "matchers/matcher_util.h"
 #include "packages/PackageInfoListener.h"
-
-#include <log/logprint.h>
-#include <utils/RefBase.h>
-#include <unordered_map>
+#include "state/StateListener.h"
 
 namespace android {
 namespace os {
@@ -86,13 +86,15 @@
 // writing the report to dropbox. MetricProducers should respond to package changes as required in
 // PackageInfoListener, but if none of the metrics are slicing by package name, then the update can
 // be a no-op.
-class MetricProducer : public virtual PackageInfoListener {
+class MetricProducer : public virtual PackageInfoListener, public virtual StateListener {
 public:
     MetricProducer(const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs,
                    const int conditionIndex, const sp<ConditionWizard>& wizard,
                    const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap,
                    const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
-                           eventDeactivationMap);
+                           eventDeactivationMap,
+                   const vector<int>& slicedStateAtoms,
+                   const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap);
 
     virtual ~MetricProducer(){};
 
@@ -151,6 +153,9 @@
         return mConditionSliced;
     };
 
+    void onStateChanged(int atomId, const HashableDimensionKey& primaryKey, int oldState,
+                        int newState){};
+
     // Output the metrics data to [protoOutput]. All metrics reports end with the same timestamp.
     // This method clears all the past buckets.
     void onDumpReport(const int64_t dumpTimeNs,
@@ -230,6 +235,11 @@
         return mBucketSizeNs;
     }
 
+    inline const std::vector<int> getSlicedStateAtoms() {
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mSlicedStateAtoms;
+    }
+
     /* If alert is valid, adds an AnomalyTracker and returns it. If invalid, returns nullptr. */
     virtual sp<AnomalyTracker> addAnomalyTracker(const Alert &alert,
                                                  const sp<AlarmMonitor>& anomalyAlarmMonitor) {
@@ -381,6 +391,16 @@
 
     bool mIsActive;
 
+    // The slice_by_state atom ids defined in statsd_config.
+    std::vector<int> mSlicedStateAtoms;
+
+    // Maps atom ids and state values to group_ids (<atom_id, <value, group_id>>).
+    std::unordered_map<int, std::unordered_map<int, int64_t>> mStateGroupMap;
+
+    FRIEND_TEST(CountMetricE2eTest, TestWithSimpleState);
+    FRIEND_TEST(CountMetricE2eTest, TestWithMappedState);
+    FRIEND_TEST(CountMetricE2eTest, TestWithMultipleStates);
+
     FRIEND_TEST(DurationMetricE2eTest, TestOneBucket);
     FRIEND_TEST(DurationMetricE2eTest, TestTwoBuckets);
     FRIEND_TEST(DurationMetricE2eTest, TestWithActivation);
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 963205e..7bae4b9 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -15,8 +15,12 @@
  */
 #define DEBUG false  // STOPSHIP if true
 #include "Log.h"
+
 #include "MetricsManager.h"
-#include "statslog.h"
+
+#include <log/logprint.h>
+#include <private/android_filesystem_config.h>
+#include <utils/SystemClock.h>
 
 #include "CountMetricProducer.h"
 #include "condition/CombinationConditionTracker.h"
@@ -25,12 +29,10 @@
 #include "matchers/CombinationLogMatchingTracker.h"
 #include "matchers/SimpleLogMatchingTracker.h"
 #include "metrics_manager_util.h"
-#include "stats_util.h"
+#include "state/StateManager.h"
 #include "stats_log_util.h"
-
-#include <log/logprint.h>
-#include <private/android_filesystem_config.h>
-#include <utils/SystemClock.h>
+#include "stats_util.h"
+#include "statslog.h"
 
 using android::util::FIELD_COUNT_REPEATED;
 using android::util::FIELD_TYPE_INT32;
@@ -149,6 +151,12 @@
 }
 
 MetricsManager::~MetricsManager() {
+    for (auto it : mAllMetricProducers) {
+        for (int atomId : it->getSlicedStateAtoms()) {
+            StateManager::getInstance().unregisterListener(atomId, it);
+        }
+    }
+
     VLOG("~MetricsManager()");
 }
 
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 3dad614..d184121 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -282,6 +282,10 @@
             TestActivationOnBootMultipleActivationsDifferentActivationTypes);
     FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
 
+    FRIEND_TEST(CountMetricE2eTest, TestWithSimpleState);
+    FRIEND_TEST(CountMetricE2eTest, TestWithMappedState);
+    FRIEND_TEST(CountMetricE2eTest, TestWithMultipleStates);
+
     FRIEND_TEST(DurationMetricE2eTest, TestOneBucket);
     FRIEND_TEST(DurationMetricE2eTest, TestTwoBuckets);
     FRIEND_TEST(DurationMetricE2eTest, TestWithActivation);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 7fe5a83..6fd0327 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -83,9 +83,11 @@
         const sp<EventMatcherWizard>& matcherWizard, const int pullTagId, const int64_t timeBaseNs,
         const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager,
         const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
-        const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap)
+        const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
+        const vector<int>& slicedStateAtoms,
+        const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
     : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, conditionWizard,
-                     eventActivationMap, eventDeactivationMap),
+                     eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap),
       mWhatMatcherIndex(whatMatcherIndex),
       mEventMatcherWizard(matcherWizard),
       mPullerManager(pullerManager),
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index d7cd397..206e602 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -52,15 +52,17 @@
 // - an alarm set to the end of the bucket
 class ValueMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
 public:
-    ValueMetricProducer(const ConfigKey& key, const ValueMetric& valueMetric,
-                        const int conditionIndex, const sp<ConditionWizard>& conditionWizard,
-                        const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard,
-                        const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs,
-                        const sp<StatsPullerManager>& pullerManager,
-                        const std::unordered_map<int, std::shared_ptr<Activation>>&
-                                eventActivationMap = {},
-                        const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
-                                eventDeactivationMap = {});
+    ValueMetricProducer(
+            const ConfigKey& key, const ValueMetric& valueMetric, const int conditionIndex,
+            const sp<ConditionWizard>& conditionWizard, const int whatMatcherIndex,
+            const sp<EventMatcherWizard>& matcherWizard, const int pullTagId,
+            const int64_t timeBaseNs, const int64_t startTimeNs,
+            const sp<StatsPullerManager>& pullerManager,
+            const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
+            const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
+                    eventDeactivationMap = {},
+            const vector<int>& slicedStateAtoms = {},
+            const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap = {});
 
     virtual ~ValueMetricProducer();
 
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 0fee71e..33e162e 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -20,24 +20,24 @@
 #include "metrics_manager_util.h"
 #include "MetricProducer.h"
 
-#include "../condition/CombinationConditionTracker.h"
-#include "../condition/SimpleConditionTracker.h"
-#include "../condition/StateConditionTracker.h"
-#include "../external/StatsPullerManager.h"
-#include "../matchers/CombinationLogMatchingTracker.h"
-#include "../matchers/SimpleLogMatchingTracker.h"
-#include "../matchers/EventMatcherWizard.h"
-#include "../metrics/CountMetricProducer.h"
-#include "../metrics/DurationMetricProducer.h"
-#include "../metrics/EventMetricProducer.h"
-#include "../metrics/GaugeMetricProducer.h"
-#include "../metrics/ValueMetricProducer.h"
+#include <inttypes.h>
 
+#include "condition/CombinationConditionTracker.h"
+#include "condition/SimpleConditionTracker.h"
+#include "condition/StateConditionTracker.h"
+#include "external/StatsPullerManager.h"
+#include "matchers/CombinationLogMatchingTracker.h"
+#include "matchers/EventMatcherWizard.h"
+#include "matchers/SimpleLogMatchingTracker.h"
+#include "metrics/CountMetricProducer.h"
+#include "metrics/DurationMetricProducer.h"
+#include "metrics/EventMetricProducer.h"
+#include "metrics/GaugeMetricProducer.h"
+#include "metrics/ValueMetricProducer.h"
+#include "state/StateManager.h"
 #include "stats_util.h"
 #include "statslog.h"
 
-#include <inttypes.h>
-
 using std::set;
 using std::string;
 using std::unordered_map;
@@ -138,6 +138,41 @@
     return true;
 }
 
+// Initializes state data structures for a metric.
+// input:
+// [config]: the input config
+// [stateIds]: the slice_by_state ids for this metric
+// [stateAtomIdMap]: this map contains the mapping from all state ids to atom ids
+// [allStateGroupMaps]: this map contains the mapping from state ids and state
+//                      values to state group ids for all states
+// output:
+// [slicedStateAtoms]: a vector of atom ids of all the slice_by_states
+// [stateGroupMap]: this map should contain the mapping from states ids and state
+//                      values to state group ids for all states that this metric
+//                      is interested in
+bool handleMetricWithStates(
+        const StatsdConfig& config, const ::google::protobuf::RepeatedField<int64_t>& stateIds,
+        const unordered_map<int64_t, int>& stateAtomIdMap,
+        const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+        vector<int>& slicedStateAtoms,
+        unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap) {
+    for (const auto& stateId : stateIds) {
+        auto it = stateAtomIdMap.find(stateId);
+        if (it == stateAtomIdMap.end()) {
+            ALOGW("cannot find State %" PRId64 " in the config", stateId);
+            return false;
+        }
+        int atomId = it->second;
+        slicedStateAtoms.push_back(atomId);
+
+        auto stateIt = allStateGroupMaps.find(stateId);
+        if (stateIt != allStateGroupMaps.end()) {
+            stateGroupMap[atomId] = stateIt->second;
+        }
+    }
+    return true;
+}
+
 // Validates a metricActivation and populates state.
 // EventActivationMap and EventDeactivationMap are supplied to a MetricProducer
 //      to provide the producer with state about its activators and deactivators.
@@ -342,12 +377,32 @@
     return true;
 }
 
+bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAtomIdMap,
+                unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps) {
+    for (int i = 0; i < config.state_size(); i++) {
+        const State& state = config.state(i);
+        const int64_t stateId = state.id();
+        stateAtomIdMap[stateId] = state.atom_id();
+
+        const StateMap& stateMap = state.map();
+        for (auto group : stateMap.group()) {
+            for (auto value : group.value()) {
+                allStateGroupMaps[stateId][value] = group.group_id();
+            }
+        }
+    }
+
+    return true;
+}
+
 bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs,
                  const int64_t currentTimeNs, UidMap& uidMap,
                  const sp<StatsPullerManager>& pullerManager,
                  const unordered_map<int64_t, int>& logTrackerMap,
                  const unordered_map<int64_t, int>& conditionTrackerMap,
                  const vector<sp<LogMatchingTracker>>& allAtomMatchers,
+                 const unordered_map<int64_t, int>& stateAtomIdMap,
+                 const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
                  vector<sp<ConditionTracker>>& allConditionTrackers,
                  vector<sp<MetricProducer>>& allMetricProducers,
                  unordered_map<int, vector<int>>& conditionToMetricMap,
@@ -398,10 +453,9 @@
 
         int conditionIndex = -1;
         if (metric.has_condition()) {
-            bool good = handleMetricWithConditions(
-                    metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
-                    allConditionTrackers, conditionIndex, conditionToMetricMap);
-            if (!good) {
+            if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
+                                            metric.links(), allConditionTrackers, conditionIndex,
+                                            conditionToMetricMap)) {
                 return false;
             }
         } else {
@@ -411,6 +465,18 @@
             }
         }
 
+        std::vector<int> slicedStateAtoms;
+        unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
+        if (metric.slice_by_state_size() > 0) {
+            if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
+                                        allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
+                return false;
+            }
+        }
+
+        // TODO(tsaichristine): add check for unequal number of MetricStateLinks
+        // and slice_by_states
+
         unordered_map<int, shared_ptr<Activation>> eventActivationMap;
         unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
         bool success = handleMetricActivation(config, metric.id(), metricIndex,
@@ -421,7 +487,7 @@
 
         sp<MetricProducer> countProducer = new CountMetricProducer(
                 key, metric, conditionIndex, wizard, timeBaseTimeNs, currentTimeNs,
-                eventActivationMap, eventDeactivationMap);
+                eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap);
         allMetricProducers.push_back(countProducer);
     }
 
@@ -721,6 +787,13 @@
     }
     for (const auto& it : allMetricProducers) {
         uidMap.addListener(it);
+
+        // Register metrics to StateTrackers
+        for (int atomId : it->getSlicedStateAtoms()) {
+            if (!StateManager::getInstance().registerListener(atomId, it)) {
+                return false;
+            }
+        }
     }
     return true;
 }
@@ -846,6 +919,8 @@
     unordered_map<int64_t, int> logTrackerMap;
     unordered_map<int64_t, int> conditionTrackerMap;
     unordered_map<int64_t, int> metricProducerMap;
+    unordered_map<int64_t, int> stateAtomIdMap;
+    unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
 
     if (!initLogTrackers(config, uidMap, logTrackerMap, allAtomMatchers, allTagIds)) {
         ALOGE("initLogMatchingTrackers failed");
@@ -858,9 +933,13 @@
         ALOGE("initConditionTrackers failed");
         return false;
     }
-
+    if (!initStates(config, stateAtomIdMap, allStateGroupMaps)) {
+        ALOGE("initStates failed");
+        return false;
+    }
     if (!initMetrics(key, config, timeBaseNs, currentTimeNs, uidMap, pullerManager, logTrackerMap,
-                     conditionTrackerMap, allAtomMatchers, allConditionTrackers, allMetricProducers,
+                     conditionTrackerMap, allAtomMatchers, stateAtomIdMap, allStateGroupMaps,
+                     allConditionTrackers, allMetricProducers,
                      conditionToMetricMap, trackerToMetricMap, metricProducerMap,
                      noReportMetricIds, activationAtomTrackerToMetricMap,
                      deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/metrics_manager_util.h
index 3802948..95b2ab8 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/metrics_manager_util.h
@@ -68,6 +68,17 @@
                     std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
                     std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks);
 
+// Initialize State maps using State protos in the config. These maps will
+// eventually be passed to MetricProducers to initialize their state info.
+// input:
+// [config]: the input config
+// output:
+// [stateAtomIdMap]: this map should contain the mapping from state ids to atom ids
+// [allStateGroupMaps]: this map should contain the mapping from states ids and state
+//                      values to state group ids for all states
+bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAtomIdMap,
+                unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps);
+
 // Initialize MetricProducers.
 // input:
 // [key]: the config key that this config belongs to
@@ -75,6 +86,9 @@
 // [timeBaseSec]: start time base for all metrics
 // [logTrackerMap]: LogMatchingTracker name to index mapping from previous step.
 // [conditionTrackerMap]: condition name to index mapping
+// [stateAtomIdMap]: contains the mapping from state ids to atom ids
+// [allStateGroupMaps]: contains the mapping from atom ids and state values to
+//                      state group ids for all states
 // output:
 // [allMetricProducers]: contains the list of sp to the MetricProducers created.
 // [conditionToMetricMap]: contains the mapping from condition tracker index to
@@ -87,6 +101,8 @@
         const std::unordered_map<int64_t, int>& conditionTrackerMap,
         const std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks,
         const vector<sp<LogMatchingTracker>>& allAtomMatchers,
+        const unordered_map<int64_t, int>& stateAtomIdMap,
+        const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
         vector<sp<ConditionTracker>>& allConditionTrackers,
         std::vector<sp<MetricProducer>>& allMetricProducers,
         std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
diff --git a/cmds/statsd/src/socket/StatsSocketListener.cpp b/cmds/statsd/src/socket/StatsSocketListener.cpp
index 92200f9..b59d88d 100755
--- a/cmds/statsd/src/socket/StatsSocketListener.cpp
+++ b/cmds/statsd/src/socket/StatsSocketListener.cpp
@@ -56,8 +56,7 @@
     }
 
     // + 1 to ensure null terminator if MAX_PAYLOAD buffer is received
-    char buffer[sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time) + LOGGER_ENTRY_MAX_PAYLOAD +
-                1];
+    char buffer[sizeof(android_log_header_t) + LOGGER_ENTRY_MAX_PAYLOAD + 1];
     struct iovec iov = {buffer, sizeof(buffer) - 1};
 
     alignas(4) char control[CMSG_SPACE(sizeof(struct ucred))];
diff --git a/cmds/statsd/src/state/StateManager.cpp b/cmds/statsd/src/state/StateManager.cpp
index a3059c5..95b2c76 100644
--- a/cmds/statsd/src/state/StateManager.cpp
+++ b/cmds/statsd/src/state/StateManager.cpp
@@ -35,26 +35,25 @@
     }
 }
 
-bool StateManager::registerListener(int stateAtomId, wp<StateListener> listener) {
+bool StateManager::registerListener(int atomId, wp<StateListener> listener) {
     std::lock_guard<std::mutex> lock(mMutex);
 
     // Check if state tracker already exists
-    if (mStateTrackers.find(stateAtomId) == mStateTrackers.end()) {
+    if (mStateTrackers.find(atomId) == mStateTrackers.end()) {
         // Create a new state tracker iff atom is a state atom
-        auto it = android::util::AtomsInfo::kStateAtomsFieldOptions.find(stateAtomId);
+        auto it = android::util::AtomsInfo::kStateAtomsFieldOptions.find(atomId);
         if (it != android::util::AtomsInfo::kStateAtomsFieldOptions.end()) {
-            mStateTrackers[stateAtomId] = new StateTracker(stateAtomId, it->second);
+            mStateTrackers[atomId] = new StateTracker(atomId, it->second);
         } else {
-            ALOGE("StateManager cannot register listener, Atom %d is not a state atom",
-                  stateAtomId);
+            ALOGE("StateManager cannot register listener, Atom %d is not a state atom", atomId);
             return false;
         }
     }
-    mStateTrackers[stateAtomId]->registerListener(listener);
+    mStateTrackers[atomId]->registerListener(listener);
     return true;
 }
 
-void StateManager::unregisterListener(int stateAtomId, wp<StateListener> listener) {
+void StateManager::unregisterListener(int atomId, wp<StateListener> listener) {
     std::unique_lock<std::mutex> lock(mMutex);
 
     // Hold the sp<> until the lock is released so that ~StateTracker() is
@@ -62,7 +61,7 @@
     sp<StateTracker> toRemove;
 
     // Unregister listener from correct StateTracker
-    auto it = mStateTrackers.find(stateAtomId);
+    auto it = mStateTrackers.find(atomId);
     if (it != mStateTrackers.end()) {
         it->second->unregisterListener(listener);
 
@@ -73,15 +72,15 @@
         }
     } else {
         ALOGE("StateManager cannot unregister listener, StateTracker for atom %d does not exist",
-              stateAtomId);
+              atomId);
     }
     lock.unlock();
 }
 
-int StateManager::getState(int stateAtomId, const HashableDimensionKey& key) {
+int StateManager::getStateValue(int atomId, const HashableDimensionKey& key) {
     std::lock_guard<std::mutex> lock(mMutex);
-    if (mStateTrackers.find(stateAtomId) != mStateTrackers.end()) {
-        return mStateTrackers[stateAtomId]->getState(key);
+    if (mStateTrackers.find(atomId) != mStateTrackers.end()) {
+        return mStateTrackers[atomId]->getStateValue(key);
     }
 
     return StateTracker::kStateUnknown;
diff --git a/cmds/statsd/src/state/StateManager.h b/cmds/statsd/src/state/StateManager.h
index ce60f14..89ee6c0 100644
--- a/cmds/statsd/src/state/StateManager.h
+++ b/cmds/statsd/src/state/StateManager.h
@@ -15,10 +15,11 @@
  */
 #pragma once
 
-//#include <utils/Log.h>
+#include <gtest/gtest_prod.h>
+#include <inttypes.h>
 #include <utils/RefBase.h>
-#include "HashableDimensionKey.h"
 
+#include "HashableDimensionKey.h"
 #include "state/StateListener.h"
 #include "state/StateTracker.h"
 
@@ -38,29 +39,29 @@
     // Notifies the correct StateTracker of an event.
     void onLogEvent(const LogEvent& event);
 
-    // Returns true if stateAtomId is the id of a state atom and notifies the
-    // correct StateTracker to register the listener. If the correct
-    // StateTracker does not exist, a new StateTracker is created.
-    bool registerListener(int stateAtomId, wp<StateListener> listener);
+    // Returns true if atomId is being tracked and is associated with a state
+    // atom. StateManager notifies the correct StateTracker to register listener.
+    // If the correct StateTracker does not exist, a new StateTracker is created.
+    bool registerListener(int atomId, wp<StateListener> listener);
 
     // Notifies the correct StateTracker to unregister a listener
     // and removes the tracker if it no longer has any listeners.
-    void unregisterListener(int stateAtomId, wp<StateListener> listener);
+    void unregisterListener(int atomId, wp<StateListener> listener);
 
-    // Queries the correct StateTracker for the state that is mapped to the given
-    // query key.
+    // Queries the correct StateTracker for the original/un-mapped state value
+    // that is mapped to the given query key.
     // If the StateTracker doesn't exist, returns StateTracker::kStateUnknown.
-    int getState(int stateAtomId, const HashableDimensionKey& queryKey);
+    int getStateValue(int atomId, const HashableDimensionKey& queryKey);
 
     inline int getStateTrackersCount() {
         std::lock_guard<std::mutex> lock(mMutex);
         return mStateTrackers.size();
     }
 
-    inline int getListenersCount(int stateAtomId) {
+    inline int getListenersCount(int atomId) {
         std::lock_guard<std::mutex> lock(mMutex);
-        if (mStateTrackers.find(stateAtomId) != mStateTrackers.end()) {
-            return mStateTrackers[stateAtomId]->getListenersCount();
+        if (mStateTrackers.find(atomId) != mStateTrackers.end()) {
+            return mStateTrackers[atomId]->getListenersCount();
         }
         return -1;
     }
diff --git a/cmds/statsd/src/state/StateTracker.cpp b/cmds/statsd/src/state/StateTracker.cpp
index 5a91950..323fc0e 100644
--- a/cmds/statsd/src/state/StateTracker.cpp
+++ b/cmds/statsd/src/state/StateTracker.cpp
@@ -30,13 +30,13 @@
   : mAtomId(atomId),
     mStateField(getSimpleMatcher(atomId, stateAtomInfo.exclusiveField)) {
     // create matcher for each primary field
-    // TODO(tsaichristine): handle when primary field is first uid in chain
+    // TODO(tsaichristine): b/142108433 handle when primary field is first uid in chain
     for (const auto& primary : stateAtomInfo.primaryFields) {
         Matcher matcher = getSimpleMatcher(atomId, primary);
         mPrimaryFields.push_back(matcher);
     }
 
-    // TODO(tsaichristine): set default state, reset state, and nesting
+    // TODO(tsaichristine): b/142108433 set default state, reset state, and nesting
 }
 
 void StateTracker::onLogEvent(const LogEvent& event) {
@@ -96,7 +96,7 @@
     mListeners.erase(listener);
 }
 
-int StateTracker::getState(const HashableDimensionKey& queryKey) const {
+int StateTracker::getStateValue(const HashableDimensionKey& queryKey) const {
     if (queryKey.getValues().size() == mPrimaryFields.size()) {
         auto it = mStateMap.find(queryKey);
         if (it != mStateMap.end()) {
diff --git a/cmds/statsd/src/state/StateTracker.h b/cmds/statsd/src/state/StateTracker.h
index f22706c..cfa9fd8 100644
--- a/cmds/statsd/src/state/StateTracker.h
+++ b/cmds/statsd/src/state/StateTracker.h
@@ -48,7 +48,7 @@
     // Returns the state value mapped to the given query key.
     // If the key isn't mapped to a state or the key size doesn't match the
     // primary key size, the default state is returned.
-    int getState(const HashableDimensionKey& queryKey) const;
+    int getStateValue(const HashableDimensionKey& queryKey) const;
 
     inline int getListenersCount() const {
         return mListeners.size();
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 67625eb..c22e3cc 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -445,6 +445,8 @@
             return 12 * 60 * 60 * 1000LL;
         case ONE_DAY:
             return 24 * 60 * 60 * 1000LL;
+        case ONE_WEEK:
+            return 7 * 24 * 60 * 60 * 1000LL;
         case CTS:
             return 1000;
         case TIME_UNIT_UNSPECIFIED:
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index c107397..0664867 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -35,7 +35,7 @@
 
 enum TimeUnit {
   TIME_UNIT_UNSPECIFIED = 0;
-  ONE_MINUTE = 1;
+  ONE_MINUTE = 1;  // WILL BE GUARDRAILED TO 5 MINS UNLESS UID = SHELL OR ROOT
   FIVE_MINUTES = 2;
   TEN_MINUTES = 3;
   THIRTY_MINUTES = 4;
@@ -44,6 +44,7 @@
   SIX_HOURS = 7;
   TWELVE_HOURS = 8;
   ONE_DAY = 9;
+  ONE_WEEK = 10;
   CTS = 1000;
 }
 
diff --git a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
new file mode 100644
index 0000000..6591d69
--- /dev/null
+++ b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
@@ -0,0 +1,197 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include "src/StatsLogProcessor.h"
+#include "src/state/StateManager.h"
+#include "tests/statsd_test_util.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+#ifdef __ANDROID__
+
+TEST(CountMetricE2eTest, TestWithSimpleState) {
+    // Initialize config
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+
+    auto syncStartMatcher = CreateSyncStartAtomMatcher();
+    *config.add_atom_matcher() = syncStartMatcher;
+
+    auto state = CreateScreenState();
+    *config.add_state() = state;
+
+    // Create count metric that slices by screen state
+    int64_t metricId = 123456;
+    auto countMetric = config.add_count_metric();
+    countMetric->set_id(metricId);
+    countMetric->set_what(syncStartMatcher.id());
+    countMetric->set_bucket(TimeUnit::ONE_MINUTE);
+    countMetric->add_slice_by_state(state.id());
+
+    // Initialize StatsLogProcessor
+    const int64_t baseTimeNs = 0;                                   // 0:00
+    const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC;  // 0:01
+    const int64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
+
+    int uid = 12345;
+    int64_t cfgId = 98765;
+    ConfigKey cfgKey(uid, cfgId);
+
+    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
+
+    // Check that StateTrackers were properly initialized.
+    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+    EXPECT_EQ(1,
+              StateManager::getInstance().getListenersCount(android::util::SCREEN_STATE_CHANGED));
+
+    // Check that CountMetricProducer was initialized correctly.
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+    EXPECT_TRUE(metricsManager->isConfigValid());
+    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), android::util::SCREEN_STATE_CHANGED);
+    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
+}
+
+TEST(CountMetricE2eTest, TestWithMappedState) {
+    // Initialize config
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+
+    auto syncStartMatcher = CreateSyncStartAtomMatcher();
+    *config.add_atom_matcher() = syncStartMatcher;
+
+    auto state = CreateScreenStateWithOnOffMap();
+    *config.add_state() = state;
+
+    // Create count metric that slices by screen state with on/off map
+    int64_t metricId = 123456;
+    auto countMetric = config.add_count_metric();
+    countMetric->set_id(metricId);
+    countMetric->set_what(syncStartMatcher.id());
+    countMetric->set_bucket(TimeUnit::ONE_MINUTE);
+    countMetric->add_slice_by_state(state.id());
+
+    // Initialize StatsLogProcessor
+    const int64_t baseTimeNs = 0;                                   // 0:00
+    const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC;  // 0:01
+    const int64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
+
+    int uid = 12345;
+    int64_t cfgId = 98765;
+    ConfigKey cfgKey(uid, cfgId);
+
+    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
+
+    // Check that StateTrackers were properly initialized.
+    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+    EXPECT_EQ(1,
+              StateManager::getInstance().getListenersCount(android::util::SCREEN_STATE_CHANGED));
+
+    // Check that CountMetricProducer was initialized correctly.
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+    EXPECT_TRUE(metricsManager->isConfigValid());
+    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), android::util::SCREEN_STATE_CHANGED);
+    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
+
+    StateMap map = state.map();
+    for (auto group : map.group()) {
+        for (auto value : group.value()) {
+            EXPECT_EQ(metricProducer->mStateGroupMap[android::util::SCREEN_STATE_CHANGED][value],
+                      group.group_id());
+        }
+    }
+}
+
+TEST(CountMetricE2eTest, TestWithMultipleStates) {
+    // Initialize config
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+
+    auto syncStartMatcher = CreateSyncStartAtomMatcher();
+    *config.add_atom_matcher() = syncStartMatcher;
+
+    auto state1 = CreateScreenStateWithOnOffMap();
+    *config.add_state() = state1;
+    auto state2 = CreateUidProcessState();
+    *config.add_state() = state2;
+
+    // Create count metric that slices by screen state with on/off map
+    int64_t metricId = 123456;
+    auto countMetric = config.add_count_metric();
+    countMetric->set_id(metricId);
+    countMetric->set_what(syncStartMatcher.id());
+    countMetric->set_bucket(TimeUnit::ONE_MINUTE);
+    countMetric->add_slice_by_state(state1.id());
+    countMetric->add_slice_by_state(state2.id());
+
+    // Initialize StatsLogProcessor
+    const int64_t baseTimeNs = 0;                                   // 0:00
+    const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC;  // 0:01
+    const int64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
+
+    int uid = 12345;
+    int64_t cfgId = 98765;
+    ConfigKey cfgKey(uid, cfgId);
+
+    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
+
+    // Check that StateTrackers were properly initialized.
+    EXPECT_EQ(2, StateManager::getInstance().getStateTrackersCount());
+    EXPECT_EQ(1,
+              StateManager::getInstance().getListenersCount(android::util::SCREEN_STATE_CHANGED));
+    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(
+                         android::util::UID_PROCESS_STATE_CHANGED));
+
+    // Check that CountMetricProducer was initialized correctly.
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+    EXPECT_TRUE(metricsManager->isConfigValid());
+    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 2);
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), android::util::SCREEN_STATE_CHANGED);
+    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(1), android::util::UID_PROCESS_STATE_CHANGED);
+    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
+
+    StateMap map = state1.map();
+    for (auto group : map.group()) {
+        for (auto value : group.value()) {
+            EXPECT_EQ(metricProducer->mStateGroupMap[android::util::SCREEN_STATE_CHANGED][value],
+                      group.group_id());
+        }
+    }
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index 839daa4..8915c73 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -43,8 +43,8 @@
     metric.set_bucket(ONE_MINUTE);
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
-    CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      5, 600 * NS_PER_SEC + NS_PER_SEC/2);
+    CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, 5,
+                                      600 * NS_PER_SEC + NS_PER_SEC / 2);
     EXPECT_EQ(600500000000, countProducer.mCurrentBucketStartTimeNs);
     EXPECT_EQ(10, countProducer.mCurrentBucketNum);
     EXPECT_EQ(660000000005, countProducer.getCurrentBucketEndTimeNs());
@@ -131,7 +131,8 @@
 
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
-    CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs, bucketStartTimeNs);
+    CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs,
+                                      bucketStartTimeNs);
 
     countProducer.onConditionChanged(true, bucketStartTimeNs);
     countProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
@@ -396,6 +397,26 @@
             std::ceil(1.0 * event7.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
 }
 
+TEST(CountMetricProducerTest, TestOneWeekTimeUnit) {
+    CountMetric metric;
+    metric.set_id(1);
+    metric.set_bucket(ONE_WEEK);
+
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+
+    int64_t oneDayNs = 24 * 60 * 60 * 1e9;
+    int64_t fiveWeeksNs = 5 * 7 * oneDayNs;
+
+    CountMetricProducer countProducer(
+            kConfigKey, metric, -1 /* meaning no condition */, wizard, oneDayNs, fiveWeeksNs);
+
+    int64_t fiveWeeksOneDayNs = fiveWeeksNs + oneDayNs;
+
+    EXPECT_EQ(fiveWeeksNs, countProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(4, countProducer.mCurrentBucketNum);
+    EXPECT_EQ(fiveWeeksOneDayNs, countProducer.getCurrentBucketEndTimeNs());
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/tests/state/StateTracker_test.cpp b/cmds/statsd/tests/state/StateTracker_test.cpp
index c89ffea..8d38000 100644
--- a/cmds/statsd/tests/state/StateTracker_test.cpp
+++ b/cmds/statsd/tests/state/StateTracker_test.cpp
@@ -44,7 +44,7 @@
 
     std::vector<Update> updates;
 
-    void onStateChanged(int stateAtomId, const HashableDimensionKey& primaryKey, int oldState,
+    void onStateChanged(int atomId, const HashableDimensionKey& primaryKey, int oldState,
                         int newState) {
         updates.emplace_back(primaryKey, newState);
     }
@@ -82,6 +82,7 @@
     return event;
 }
 
+// Incorrect event - missing fields
 std::shared_ptr<LogEvent> buildIncorrectOverlayEvent(int uid, const std::string& packageName, int state) {
     std::shared_ptr<LogEvent> event =
             std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
@@ -91,6 +92,18 @@
     event->init();
     return event;
 }
+
+// Incorrect event - exclusive state has wrong type
+std::shared_ptr<LogEvent> buildOverlayEventBadStateType(int uid, const std::string& packageName) {
+    std::shared_ptr<LogEvent> event =
+            std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
+    event->write((int32_t)uid);
+    event->write(packageName);
+    event->write(true);
+    event->write("string");  // exclusive state: string instead of int
+    event->init();
+    return event;
+}
 // END: build event functions.
 
 // START: get primary key functions
@@ -148,22 +161,22 @@
 
     // Register listener to non-existing StateTracker
     EXPECT_EQ(0, mgr.getStateTrackersCount());
-    mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
+    EXPECT_TRUE(mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1));
     EXPECT_EQ(1, mgr.getStateTrackersCount());
     EXPECT_EQ(1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
 
     // Register listener to existing StateTracker
-    mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener2);
+    EXPECT_TRUE(mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener2));
     EXPECT_EQ(1, mgr.getStateTrackersCount());
     EXPECT_EQ(2, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
 
     // Register already registered listener to existing StateTracker
-    mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener2);
+    EXPECT_TRUE(mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener2));
     EXPECT_EQ(1, mgr.getStateTrackersCount());
     EXPECT_EQ(2, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
 
     // Register listener to non-state atom
-    mgr.registerListener(android::util::BATTERY_LEVEL_CHANGED, listener2);
+    EXPECT_FALSE(mgr.registerListener(android::util::BATTERY_LEVEL_CHANGED, listener2));
     EXPECT_EQ(1, mgr.getStateTrackersCount());
 }
 
@@ -227,12 +240,12 @@
 
     // check StateTracker was updated by querying for state
     HashableDimensionKey queryKey = DEFAULT_DIMENSION_KEY;
-    EXPECT_EQ(2, mgr.getState(android::util::SCREEN_STATE_CHANGED, queryKey));
+    EXPECT_EQ(2, mgr.getStateValue(android::util::SCREEN_STATE_CHANGED, queryKey));
 }
 
 /**
  * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
- * updates listener for states with primary keys.
+ * updates listener for states with one primary key.
  */
 TEST(StateTrackerTest, TestStateChangeOnePrimaryField) {
     sp<TestStateListener> listener1 = new TestStateListener();
@@ -240,9 +253,8 @@
     mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener1);
 
     // log event
-    std::shared_ptr<LogEvent> event = buildUidProcessEvent(
-            1000,
-            android::app::ProcessStateEnum::PROCESS_STATE_TOP);  //  state value: 1002
+    std::shared_ptr<LogEvent> event =
+            buildUidProcessEvent(1000 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP);
     mgr.onLogEvent(*event);
 
     // check listener was updated
@@ -252,23 +264,33 @@
 
     // check StateTracker was updated by querying for state
     HashableDimensionKey queryKey;
-    getUidProcessKey(1000, &queryKey);
-    EXPECT_EQ(1002, mgr.getState(android::util::UID_PROCESS_STATE_CHANGED, queryKey));
+    getUidProcessKey(1000 /* uid */, &queryKey);
+    EXPECT_EQ(1002, mgr.getStateValue(android::util::UID_PROCESS_STATE_CHANGED, queryKey));
 }
 
+/**
+ * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
+ * updates listener for states with multiple primary keys.
+ */
 TEST(StateTrackerTest, TestStateChangeMultiplePrimaryFields) {
     sp<TestStateListener> listener1 = new TestStateListener();
     StateManager mgr;
     mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
 
     // log event
-    std::shared_ptr<LogEvent> event = buildOverlayEvent(1000, "package1", 1);  // state: ENTERED
+    std::shared_ptr<LogEvent> event =
+            buildOverlayEvent(1000 /* uid */, "package1", 1);  // state: ENTERED
     mgr.onLogEvent(*event);
 
-    // check listener update
+    // check listener was updated
     EXPECT_EQ(1, listener1->updates.size());
     EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
     EXPECT_EQ(1, listener1->updates[0].mState);
+
+    // check StateTracker was updated by querying for state
+    HashableDimensionKey queryKey;
+    getOverlayKey(1000 /* uid */, "package1", &queryKey);
+    EXPECT_EQ(1, mgr.getStateValue(android::util::OVERLAY_STATE_CHANGED, queryKey));
 }
 
 /**
@@ -282,11 +304,14 @@
     mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
 
     // log event
-    std::shared_ptr<LogEvent> event =
-            buildIncorrectOverlayEvent(1000, "package1", 1);  // state: ENTERED
-    mgr.onLogEvent(*event);
+    std::shared_ptr<LogEvent> event1 =
+            buildIncorrectOverlayEvent(1000 /* uid */, "package1", 1 /* state */);
+    std::shared_ptr<LogEvent> event2 = buildOverlayEventBadStateType(1001 /* uid */, "package2");
 
-    // check listener update
+    // check listener was updated
+    mgr.onLogEvent(*event1);
+    EXPECT_EQ(0, listener1->updates.size());
+    mgr.onLogEvent(*event2);
     EXPECT_EQ(0, listener1->updates.size());
 }
 
@@ -301,18 +326,19 @@
 
     std::shared_ptr<LogEvent> event1 = buildUidProcessEvent(
             1000,
-            android::app::ProcessStateEnum::PROCESS_STATE_TOP);  // state value: 1002
+            android::app::ProcessStateEnum::PROCESS_STATE_TOP);  //  state value: 1002
     std::shared_ptr<LogEvent> event2 = buildUidProcessEvent(
             1001,
-            android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE);  // state value: 1003
+            android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE);  //  state value:
+                                                                                //  1003
     std::shared_ptr<LogEvent> event3 = buildUidProcessEvent(
             1002,
-            android::app::ProcessStateEnum::PROCESS_STATE_PERSISTENT);  // state value: 1000
+            android::app::ProcessStateEnum::PROCESS_STATE_PERSISTENT);  //  state value: 1000
     std::shared_ptr<LogEvent> event4 = buildUidProcessEvent(
             1001,
-            android::app::ProcessStateEnum::PROCESS_STATE_TOP);  // state value: 1002
+            android::app::ProcessStateEnum::PROCESS_STATE_TOP);  //  state value: 1002
     std::shared_ptr<LogEvent> event5 =
-            buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);  // state value:
+            buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
     std::shared_ptr<LogEvent> event6 = buildOverlayEvent(1000, "package1", 1);
     std::shared_ptr<LogEvent> event7 = buildOverlayEvent(1000, "package2", 2);
 
@@ -327,25 +353,25 @@
     // Query for UidProcessState of uid 1001
     HashableDimensionKey queryKey1;
     getUidProcessKey(1001, &queryKey1);
-    EXPECT_EQ(1003, mgr.getState(android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
+    EXPECT_EQ(1003, mgr.getStateValue(android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
 
     // Query for UidProcessState of uid 1004 - not in state map
     HashableDimensionKey queryKey2;
     getUidProcessKey(1004, &queryKey2);
-    EXPECT_EQ(-1,
-              mgr.getState(android::util::UID_PROCESS_STATE_CHANGED, queryKey2));  // default state
+    EXPECT_EQ(-1, mgr.getStateValue(android::util::UID_PROCESS_STATE_CHANGED,
+                                    queryKey2));  // default state
 
     // Query for UidProcessState of uid 1001 - after change in state
     mgr.onLogEvent(*event4);
-    EXPECT_EQ(1002, mgr.getState(android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
+    EXPECT_EQ(1002, mgr.getStateValue(android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
 
     // Query for ScreenState
-    EXPECT_EQ(2, mgr.getState(android::util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY));
+    EXPECT_EQ(2, mgr.getStateValue(android::util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY));
 
     // Query for OverlayState of uid 1000, package name "package2"
     HashableDimensionKey queryKey3;
     getOverlayKey(1000, "package2", &queryKey3);
-    EXPECT_EQ(2, mgr.getState(android::util::OVERLAY_STATE_CHANGED, queryKey3));
+    EXPECT_EQ(2, mgr.getStateValue(android::util::OVERLAY_STATE_CHANGED, queryKey3));
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index 2c4f3c7..38c22ab 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -251,6 +251,101 @@
     return predicate;
 }
 
+State CreateScreenState() {
+    State state;
+    state.set_id(StringToId("ScreenState"));
+    state.set_atom_id(29);
+    return state;
+}
+
+State CreateUidProcessState() {
+    State state;
+    state.set_id(StringToId("UidProcessState"));
+    state.set_atom_id(27);
+    return state;
+}
+
+State CreateOverlayState() {
+    State state;
+    state.set_id(StringToId("OverlayState"));
+    state.set_atom_id(59);
+    return state;
+}
+
+State CreateScreenStateWithOnOffMap() {
+    State state;
+    state.set_id(StringToId("ScreenStateOnOff"));
+    state.set_atom_id(29);
+
+    auto map = CreateScreenStateOnOffMap();
+    *state.mutable_map() = map;
+
+    return state;
+}
+
+State CreateScreenStateWithInDozeMap() {
+    State state;
+    state.set_id(StringToId("ScreenStateInDoze"));
+    state.set_atom_id(29);
+
+    auto map = CreateScreenStateInDozeMap();
+    *state.mutable_map() = map;
+
+    return state;
+}
+
+StateMap_StateGroup CreateScreenStateOnGroup() {
+    StateMap_StateGroup group;
+    group.set_group_id(StringToId("SCREEN_ON"));
+    group.add_value(2);
+    group.add_value(5);
+    group.add_value(6);
+    return group;
+}
+
+StateMap_StateGroup CreateScreenStateOffGroup() {
+    StateMap_StateGroup group;
+    group.set_group_id(StringToId("SCREEN_OFF"));
+    group.add_value(0);
+    group.add_value(1);
+    group.add_value(3);
+    group.add_value(4);
+    return group;
+}
+
+StateMap CreateScreenStateOnOffMap() {
+    StateMap map;
+    *map.add_group() = CreateScreenStateOnGroup();
+    *map.add_group() = CreateScreenStateOffGroup();
+    return map;
+}
+
+StateMap_StateGroup CreateScreenStateInDozeGroup() {
+    StateMap_StateGroup group;
+    group.set_group_id(StringToId("SCREEN_DOZE"));
+    group.add_value(3);
+    group.add_value(4);
+    return group;
+}
+
+StateMap_StateGroup CreateScreenStateNotDozeGroup() {
+    StateMap_StateGroup group;
+    group.set_group_id(StringToId("SCREEN_NOT_DOZE"));
+    group.add_value(0);
+    group.add_value(1);
+    group.add_value(2);
+    group.add_value(5);
+    group.add_value(6);
+    return group;
+}
+
+StateMap CreateScreenStateInDozeMap() {
+    StateMap map;
+    *map.add_group() = CreateScreenStateInDozeGroup();
+    *map.add_group() = CreateScreenStateNotDozeGroup();
+    return map;
+}
+
 void addPredicateToPredicateCombination(const Predicate& predicate,
                                         Predicate* combinationPredicate) {
     combinationPredicate->mutable_combination()->add_predicate(predicate.id());
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index 635c583..c026105 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -104,6 +104,37 @@
 // Create a Predicate proto for app is in background.
 Predicate CreateIsInBackgroundPredicate();
 
+// Create State proto for screen state atom.
+State CreateScreenState();
+
+// Create State proto for uid process state atom.
+State CreateUidProcessState();
+
+// Create State proto for overlay state atom.
+State CreateOverlayState();
+
+State CreateScreenStateWithOnOffMap();
+
+State CreateScreenStateWithInDozeMap();
+
+// Create StateGroup proto for ScreenState ON group
+StateMap_StateGroup CreateScreenStateOnGroup();
+
+// Create StateGroup proto for ScreenState OFF group
+StateMap_StateGroup CreateScreenStateOffGroup();
+
+// Create StateMap proto for ScreenState ON/OFF map
+StateMap CreateScreenStateOnOffMap();
+
+// Create StateGroup proto for ScreenState IN DOZE group
+StateMap_StateGroup CreateScreenStateInDozeGroup();
+
+// Create StateGroup proto for ScreenState NOT IN DOZE group
+StateMap_StateGroup CreateScreenStateNotDozeGroup();
+
+// Create StateMap proto for ScreenState IN DOZE map
+StateMap CreateScreenStateInDozeMap();
+
 // Add a predicate to the predicate combination.
 void addPredicateToPredicateCombination(const Predicate& predicate, Predicate* combination);
 
@@ -319,4 +350,4 @@
 }
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 4603f08..47fdcde 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -850,6 +850,7 @@
         GestureResultCallbackInfo callbackInfo;
         synchronized (mLock) {
             callbackInfo = mGestureStatusCallbackInfos.get(sequence);
+            mGestureStatusCallbackInfos.remove(sequence);
         }
         final GestureResultCallbackInfo finalCallbackInfo = callbackInfo;
         if ((callbackInfo != null) && (callbackInfo.gestureDescription != null)
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index cf24b8e..e738b19 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
 
+import android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.UnsupportedAppUsage;
@@ -322,6 +323,14 @@
      */
     public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 0x00000400;
 
+    /**
+     * This flag indicates that the accessibility service will handle the shortcut action itself.
+     * A callback {@link AccessibilityButtonCallback#onClicked(AccessibilityButtonController)} is
+     * called when the user presses the accessibility shortcut. Otherwise, the service is enabled
+     * or disabled by the system instead.
+     */
+    public static final int FLAG_HANDLE_SHORTCUT = 0x00000800;
+
     /** {@hide} */
     public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
 
@@ -423,12 +432,13 @@
      * @see #FLAG_ENABLE_ACCESSIBILITY_VOLUME
      * @see #FLAG_REQUEST_ACCESSIBILITY_BUTTON
      * @see #FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK
+     * @see #FLAG_HANDLE_SHORTCUT
      */
     public int flags;
 
     /**
      * Whether or not the service has crashed and is awaiting restart. Only valid from {@link
-     * android.view.accessibility.AccessibilityManager#getEnabledAccessibilityServiceList(int)},
+     * android.view.accessibility.AccessibilityManager#getInstalledAccessibilityServiceList()},
      * because that is populated from the internal list of running services.
      *
      * @hide
@@ -1103,6 +1113,8 @@
                 return "FLAG_REQUEST_FINGERPRINT_GESTURES";
             case FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK:
                 return "FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK";
+            case FLAG_HANDLE_SHORTCUT:
+                return "FLAG_HANDLE_SHORTCUT";
             default:
                 return null;
         }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 03300e4..2c57622 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -7097,14 +7097,28 @@
     }
 
     /**
-     * Convert a translucent themed Activity {@link android.R.attr#windowIsTranslucent} to a
-     * fullscreen opaque Activity.
+     * Convert an activity, which particularly with {@link android.R.attr#windowIsTranslucent} or
+     * {@link android.R.attr#windowIsFloating} attribute, to a fullscreen opaque activity, or
+     * convert it from opaque back to translucent.
+     *
+     * @param translucent {@code true} convert from opaque to translucent.
+     *                    {@code false} convert from translucent to opaque.
+     * @return The result of setting translucency. Return {@code true} if set successfully,
+     *         {@code false} otherwise.
+     */
+    public boolean setTranslucent(boolean translucent) {
+        if (translucent) {
+            return convertToTranslucent(null /* callback */, null /* options */);
+        } else {
+            return convertFromTranslucentInternal();
+        }
+    }
+
+    /**
+     * Convert an activity to a fullscreen opaque activity.
      * <p>
-     * Call this whenever the background of a translucent Activity has changed to become opaque.
-     * Doing so will allow the {@link android.view.Surface} of the Activity behind to be released.
-     * <p>
-     * This call has no effect on non-translucent activities or on activities with the
-     * {@link android.R.attr#windowIsFloating} attribute.
+     * Call this whenever the background of a translucent activity has changed to become opaque.
+     * Doing so will allow the {@link android.view.Surface} of the activity behind to be released.
      *
      * @see #convertToTranslucent(android.app.Activity.TranslucentConversionListener,
      * ActivityOptions)
@@ -7114,31 +7128,33 @@
      */
     @SystemApi
     public void convertFromTranslucent() {
+        convertFromTranslucentInternal();
+    }
+
+    private boolean convertFromTranslucentInternal() {
         try {
             mTranslucentCallback = null;
             if (ActivityTaskManager.getService().convertFromTranslucent(mToken)) {
                 WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, true);
+                return true;
             }
         } catch (RemoteException e) {
             // pass
         }
+        return false;
     }
 
     /**
-     * Convert a translucent themed Activity {@link android.R.attr#windowIsTranslucent} back from
-     * opaque to translucent following a call to {@link #convertFromTranslucent()}.
+     * Convert an activity to a translucent activity.
      * <p>
-     * Calling this allows the Activity behind this one to be seen again. Once all such Activities
+     * Calling this allows the activity behind this one to be seen again. Once all such activities
      * have been redrawn {@link TranslucentConversionListener#onTranslucentConversionComplete} will
      * be called indicating that it is safe to make this activity translucent again. Until
      * {@link TranslucentConversionListener#onTranslucentConversionComplete} is called the image
-     * behind the frontmost Activity will be indeterminate.
-     * <p>
-     * This call has no effect on non-translucent activities or on activities with the
-     * {@link android.R.attr#windowIsFloating} attribute.
+     * behind the frontmost activity will be indeterminate.
      *
-     * @param callback the method to call when all visible Activities behind this one have been
-     * drawn and it is safe to make this Activity translucent again.
+     * @param callback the method to call when all visible activities behind this one have been
+     * drawn and it is safe to make this activity translucent again.
      * @param options activity options delivered to the activity below this one. The options
      * are retrieved using {@link #getActivityOptions}.
      * @return <code>true</code> if Window was opaque and will become translucent or
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 1649e8b..d5e41f0 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -50,6 +50,7 @@
 import android.util.ArrayMap;
 import android.util.LongSparseArray;
 import android.util.LongSparseLongArray;
+import android.util.Pair;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
@@ -77,10 +78,12 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
+import java.util.function.ToLongFunction;
 
 /**
  * API for interacting with "application operation" tracking.
@@ -2052,7 +2055,7 @@
      *
      * @see #markAppOpNoted
      */
-    private static final ThreadLocal<long[]> sAppOpsNotedInThisBinderTransaction =
+    private static final ThreadLocal<ArrayMap<String, long[]>> sAppOpsNotedInThisBinderTransaction =
             new ThreadLocal<>();
 
     /** Whether noting for an appop should be collected */
@@ -2329,51 +2332,42 @@
     }
 
     /**
-     * Class holding the information about one unique operation of an application.
+     * Class holding the information about one unique operation of a
+     * {@link Context#createFeatureContext(String) feature}.
+     *
      * @hide
      */
     @TestApi
     @Immutable
     @SystemApi
-    public static final class OpEntry implements Parcelable {
-        private final int mOp;
+    public static final class OpFeatureEntry {
+        private final @NonNull OpEntry mParent;
         private final boolean mRunning;
-        private final @Mode int mMode;
+
         private final @Nullable LongSparseLongArray mAccessTimes;
         private final @Nullable LongSparseLongArray mRejectTimes;
         private final @Nullable LongSparseLongArray mDurations;
         private final @Nullable LongSparseLongArray mProxyUids;
         private final @Nullable LongSparseArray<String> mProxyPackageNames;
+        private final @Nullable LongSparseArray<String> mProxyFeatureIds;
 
         /**
          * @hide
          */
-        public OpEntry(int op, boolean running, @Mode int mode,
-                @Nullable LongSparseLongArray accessTimes, @Nullable LongSparseLongArray rejectTimes,
+        public OpFeatureEntry(@NonNull OpEntry parent, boolean running,
+                @Nullable LongSparseLongArray accessTimes,
+                @Nullable LongSparseLongArray rejectTimes,
                 @Nullable LongSparseLongArray durations, @Nullable LongSparseLongArray proxyUids,
-                @Nullable LongSparseArray<String> proxyPackageNames) {
-            mOp = op;
+                @Nullable LongSparseArray<String> proxyPackageNames,
+                @Nullable LongSparseArray<String> proxyFeatureIds) {
+            mParent = Preconditions.checkNotNull(parent);
             mRunning = running;
-            mMode = mode;
             mAccessTimes = accessTimes;
             mRejectTimes = rejectTimes;
             mDurations = durations;
             mProxyUids = proxyUids;
             mProxyPackageNames = proxyPackageNames;
-        }
-
-        /**
-         * @hide
-         */
-        public OpEntry(int op, @Mode int mode) {
-            mOp = op;
-            mMode = mode;
-            mRunning = false;
-            mAccessTimes = null;
-            mRejectTimes = null;
-            mDurations = null;
-            mProxyUids = null;
-            mProxyPackageNames = null;
+            mProxyFeatureIds = proxyFeatureIds;
         }
 
         /**
@@ -2390,29 +2384,6 @@
         /**
          * @hide
          */
-        @UnsupportedAppUsage
-        public int getOp() {
-            return mOp;
-        }
-
-        /**
-         * @return This entry's op string name, such as {@link #OPSTR_COARSE_LOCATION}.
-         */
-        public @NonNull String getOpStr() {
-            return sOpToString[mOp];
-        }
-
-        /**
-         * @return this entry's current mode, such as {@link #MODE_ALLOWED}.
-         */
-        public @Mode int getMode() {
-            return mMode;
-        }
-
-        /**
-         * @hide
-         */
-        @UnsupportedAppUsage
         public long getTime() {
             return getLastAccessTime(OP_FLAGS_ALL);
         }
@@ -2455,7 +2426,7 @@
          */
         public long getLastAccessForegroundTime(@OpFlags int flags) {
             return maxForFlagsInStates(mAccessTimes, MAX_PRIORITY_UID_STATE,
-                    resolveFirstUnrestrictedUidState(mOp), flags);
+                    resolveFirstUnrestrictedUidState(mParent.mOp), flags);
         }
 
         /**
@@ -2475,7 +2446,7 @@
          * @see #getLastAccessTime(int, int, int)
          */
         public long getLastAccessBackgroundTime(@OpFlags int flags) {
-            return maxForFlagsInStates(mAccessTimes, resolveLastRestrictedUidState(mOp),
+            return maxForFlagsInStates(mAccessTimes, resolveLastRestrictedUidState(mParent.mOp),
                     MIN_PRIORITY_UID_STATE, flags);
         }
 
@@ -2509,7 +2480,6 @@
         /**
          * @hide
          */
-        @UnsupportedAppUsage
         public long getRejectTime() {
             return getLastRejectTime(OP_FLAGS_ALL);
         }
@@ -2553,7 +2523,7 @@
          */
         public long getLastRejectForegroundTime(@OpFlags int flags) {
             return maxForFlagsInStates(mRejectTimes, MAX_PRIORITY_UID_STATE,
-                    resolveFirstUnrestrictedUidState(mOp), flags);
+                    resolveFirstUnrestrictedUidState(mParent.mOp), flags);
         }
 
         /**
@@ -2573,7 +2543,7 @@
          * @see #getLastRejectTime(int)
          */
         public long getLastRejectBackgroundTime(@OpFlags int flags) {
-            return maxForFlagsInStates(mRejectTimes, resolveLastRestrictedUidState(mOp),
+            return maxForFlagsInStates(mRejectTimes, resolveLastRestrictedUidState(mParent.mOp),
                     MIN_PRIORITY_UID_STATE, flags);
         }
 
@@ -2633,7 +2603,7 @@
          */
         public long getLastForegroundDuration(@OpFlags int flags) {
             return sumForFlagsInStates(mDurations, MAX_PRIORITY_UID_STATE,
-                    resolveFirstUnrestrictedUidState(mOp), flags);
+                    resolveFirstUnrestrictedUidState(mParent.mOp), flags);
         }
 
         /**
@@ -2651,7 +2621,7 @@
          * @see #getLastDuration(int, int, int)
          */
         public long getLastBackgroundDuration(@OpFlags int flags) {
-            return sumForFlagsInStates(mDurations, resolveLastRestrictedUidState(mOp),
+            return sumForFlagsInStates(mDurations, resolveLastRestrictedUidState(mParent.mOp),
                     MIN_PRIORITY_UID_STATE, flags);
         }
 
@@ -2736,12 +2706,663 @@
          * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
          * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
          * for any flag.
-         * @return The proxy package name.
+         * @return The feature id.
          */
         public @Nullable String getProxyPackageName(@UidState int uidState, @OpFlags int flags) {
             return findFirstNonNullForFlagsInStates(mProxyPackageNames, uidState, uidState, flags);
         }
 
+        /**
+         * Gets the feature of the app that performed the op on behalf of this
+         * app and as a result blamed the op on this app or {@code null}
+         * if there is no proxy.
+         *
+         * @return The proxy package name.
+         */
+        public @Nullable String getProxyFeatureId() {
+            return findFirstNonNullForFlagsInStates(mProxyFeatureIds, MAX_PRIORITY_UID_STATE,
+                    MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+        }
+
+        /**
+         * Gets the feature of the app that performed the op on behalf of this
+         * app and as a result blamed the op on this app for a UID state or
+         * {@code null} if there is no proxy.
+         *
+         * @param uidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return The feature id.
+         */
+        public @Nullable String getProxyFeatureId(@UidState int uidState, @OpFlags int flags) {
+            return findFirstNonNullForFlagsInStates(mProxyFeatureIds, uidState, uidState, flags);
+        }
+
+        /**
+         * @hide
+         */
+        public static class Builder {
+            private final boolean mRunning;
+
+            private final @Nullable LongSparseLongArray mAccessTimes;
+            private final @Nullable LongSparseLongArray mRejectTimes;
+            private final @Nullable LongSparseLongArray mDurations;
+            private final @Nullable LongSparseLongArray mProxyUids;
+            private final @Nullable LongSparseArray<String> mProxyPackageNames;
+            private final @Nullable LongSparseArray<String> mProxyFeatureIds;
+            private @NonNull OpEntry mParent;
+
+            public Builder(boolean running, @Nullable LongSparseLongArray accessTimes,
+                    @Nullable LongSparseLongArray rejectTimes,
+                    @Nullable LongSparseLongArray durations,
+                    @Nullable LongSparseLongArray proxyUids,
+                    @Nullable LongSparseArray<String> proxyPackageNames,
+                    @Nullable LongSparseArray<String> proxyFeatureIds) {
+                mRunning = running;
+                mAccessTimes = accessTimes;
+                mRejectTimes = rejectTimes;
+                mDurations = durations;
+                mProxyUids = proxyUids;
+                mProxyPackageNames = proxyPackageNames;
+                mProxyFeatureIds = proxyFeatureIds;
+            }
+
+            public Builder setParent(@NonNull OpEntry parent) {
+                mParent = parent;
+
+                return this;
+            }
+
+            /**
+             * Create OpFeatureEntry from builder
+             */
+            public OpFeatureEntry build() {
+                Preconditions.checkNotNull(mParent);
+
+                return new OpFeatureEntry(mParent, mRunning, mAccessTimes, mRejectTimes,
+                        mDurations, mProxyUids, mProxyPackageNames, mProxyFeatureIds);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            LongSparseLongArray.Parcelling longSparseLongArrayParcelling =
+                    LongSparseLongArray.Parcelling.Cache.getOrCreate(
+                            LongSparseLongArray.Parcelling.class);
+            LongSparseArray.StringParcelling longSparseStringArrayParcelling =
+                    LongSparseArray.StringParcelling.Cache.getOrCreate(
+                            LongSparseArray.StringParcelling.class);
+
+            dest.writeBoolean(mRunning);
+            longSparseLongArrayParcelling.parcel(mAccessTimes, dest, flags);
+            longSparseLongArrayParcelling.parcel(mRejectTimes, dest, flags);
+            longSparseLongArrayParcelling.parcel(mDurations, dest, flags);
+            longSparseLongArrayParcelling.parcel(mProxyUids, dest, flags);
+            longSparseStringArrayParcelling.parcel(mProxyPackageNames, dest, flags);
+            longSparseStringArrayParcelling.parcel(mProxyFeatureIds, dest, flags);
+        }
+
+        /**
+         * @hide
+         */
+        public static OpFeatureEntry.Builder createFromParcel(@NonNull Parcel source) {
+            LongSparseLongArray.Parcelling longSparseLongArrayParcelling =
+                    LongSparseLongArray.Parcelling.Cache.getOrCreate(
+                            LongSparseLongArray.Parcelling.class);
+            LongSparseArray.StringParcelling longSparseStringArrayParcelling =
+                    LongSparseArray.StringParcelling.Cache.getOrCreate(
+                            LongSparseArray.StringParcelling.class);
+
+            return new OpFeatureEntry.Builder(source.readBoolean(),
+                    (LongSparseLongArray) longSparseLongArrayParcelling.unparcel(source),
+                    (LongSparseLongArray) longSparseLongArrayParcelling.unparcel(source),
+                    (LongSparseLongArray) longSparseLongArrayParcelling.unparcel(source),
+                    (LongSparseLongArray) longSparseLongArrayParcelling.unparcel(source),
+                    (LongSparseArray<String>) longSparseStringArrayParcelling.unparcel(source),
+                    (LongSparseArray<String>) longSparseStringArrayParcelling.unparcel(source));
+        }
+    }
+
+    /**
+     * Class holding the information about one unique operation of an application.
+     * @hide
+     */
+    @TestApi
+    @Immutable
+    @SystemApi
+    public static final class OpEntry implements Parcelable {
+        private final @IntRange(from = 0, to = _NUM_OP - 1) int mOp;
+        private final @Mode int mMode;
+        private final @NonNull ArrayMap<String, OpFeatureEntry> mFeatures;
+
+        /**
+         * @hide
+         */
+        public OpEntry(@IntRange(from = 0, to = _NUM_OP - 1) int op, @Mode int mode,
+                @NonNull Pair<String, OpFeatureEntry.Builder>[] featureBuilders) {
+            mOp = Preconditions.checkArgumentInRange(op, 0, _NUM_OP - 1, "op");
+            mMode = Preconditions.checkArgumentInRange(mode, 0, MODE_FOREGROUND, "mode");
+
+            mFeatures = new ArrayMap<>(featureBuilders.length);
+            for (Pair<String, OpFeatureEntry.Builder> feature : featureBuilders) {
+                mFeatures.put(feature.first, feature.second.setParent(this).build());
+            }
+        }
+
+        /**
+         * @return The mapping from the feature ids to the feature state
+         */
+        public @NonNull Map<String, OpFeatureEntry> getFeatures() {
+            return mFeatures;
+        }
+
+        /**
+         * @hide
+         */
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "{@code "
+                + "#getOpStr()}")
+        public int getOp() {
+            return mOp;
+        }
+
+        /**
+         * @return This entry's op string name, such as {@link #OPSTR_COARSE_LOCATION}.
+         */
+        public @NonNull String getOpStr() {
+            return sOpToString[mOp];
+        }
+
+        /**
+         * @return this entry's current mode, such as {@link #MODE_ALLOWED}.
+         */
+        public @Mode int getMode() {
+            return mMode;
+        }
+
+        /**
+         * @deprecated Use {@link OpEntry#getLastAccessTime(int)} instead
+         *
+         * @hide
+         */
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "{@code "
+                + "#getLastAccessTime(int)}")
+        public long getTime() {
+            return getLastAccessTime(OP_FLAGS_ALL);
+        }
+
+        private long getMaxOfFeatures(@NonNull ToLongFunction<OpFeatureEntry> timeGetter) {
+            long max = 0;
+
+            int numFeatures = mFeatures.size();
+            for (int i = 0; i < numFeatures; i++) {
+                max = Math.max(max, timeGetter.applyAsLong(mFeatures.valueAt(i)));
+            }
+
+            return max;
+        }
+
+        private long getSumOfFeatures(@NonNull ToLongFunction<OpFeatureEntry> getter) {
+            long sum = 0;
+
+            int numFeatures = mFeatures.size();
+            for (int i = 0; i < numFeatures; i++) {
+                sum += getter.applyAsLong(mFeatures.valueAt(i));
+            }
+
+            return sum;
+        }
+
+        /**
+         * Return the last wall clock time  in milliseconds this op was accessed
+         * by the app for a given range of UID states.
+         *
+         * @param fromUidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state for which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         *
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastAccessForegroundTime(int)
+         * @see #getLastAccessBackgroundTime(int)
+         * @see #getLastAccessTime(int)
+         */
+        public long getLastAccessTime(@OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastAccessTime(flags)));
+        }
+
+        /**
+         * Return the last wall clock time in milliseconds this op was accessed
+         * by the app while in the foreground.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastAccessBackgroundTime(int)
+         * @see #getLastAccessTime(int)
+         * @see #getLastAccessTime(int, int, int)
+         */
+        public long getLastAccessForegroundTime(@OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastAccessForegroundTime(flags)));
+        }
+
+        /**
+         * Return the last wall clock time in milliseconds this op was accessed
+         * by the app while in the background.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastAccessForegroundTime(int)
+         * @see #getLastAccessTime(int)
+         * @see #getLastAccessTime(int, int, int)
+         */
+        public long getLastAccessBackgroundTime(@OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastAccessBackgroundTime(flags)));
+        }
+
+        /**
+         * Return the last wall clock time  in milliseconds this op was accessed
+         * by the app for a given range of UID states.
+         *
+         * @param fromUidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state for which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         *
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastAccessForegroundTime(int)
+         * @see #getLastAccessBackgroundTime(int)
+         * @see #getLastAccessTime(int)
+         */
+        public long getLastAccessTime(@UidState int fromUidState, @UidState int toUidState,
+                @OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastAccessTime(fromUidState,
+                            toUidState, flags)));
+        }
+
+        /**
+         * @deprecated Use {@link OpEntry#getLastRejectTime(int)} instead
+         *
+         * @hide
+         */
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "{@code "
+                + "#getLastRejectTime(int)}")
+        public long getRejectTime() {
+            return getLastRejectTime(OP_FLAGS_ALL);
+        }
+
+        /**
+         * Return the last wall clock time in milliseconds the app made an attempt
+         * to access this op but was rejected.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last reject time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastRejectBackgroundTime(int)
+         * @see #getLastRejectForegroundTime(int)
+         * @see #getLastRejectTime(int, int, int)
+         */
+        public long getLastRejectTime(@OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastRejectTime(flags)));
+        }
+
+        /**
+         * Return the last wall clock time in milliseconds the app made an attempt
+         * to access this op while in the foreground but was rejected.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last foreground reject time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastRejectBackgroundTime(int)
+         * @see #getLastRejectTime(int, int, int)
+         * @see #getLastRejectTime(int)
+         */
+        public long getLastRejectForegroundTime(@OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastRejectForegroundTime(flags)));
+        }
+
+        /**
+         * Return the last wall clock time in milliseconds the app made an attempt
+         * to access this op while in the background but was rejected.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last background reject time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastRejectForegroundTime(int)
+         * @see #getLastRejectTime(int, int, int)
+         * @see #getLastRejectTime(int)
+         */
+        public long getLastRejectBackgroundTime(@OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastRejectBackgroundTime(flags)));
+        }
+
+        /**
+         * Return the last wall clock time state in milliseconds the app made an
+         * attempt to access this op for a given range of UID states.
+         *
+         * @param fromUidState The UID state from which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state to which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastRejectForegroundTime(int)
+         * @see #getLastRejectBackgroundTime(int)
+         * @see #getLastRejectTime(int)
+         */
+        public long getLastRejectTime(@UidState int fromUidState, @UidState int toUidState,
+                @OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastRejectTime(fromUidState,
+                            toUidState, flags)));
+        }
+
+        /**
+         * @return Whether the operation is running.
+         */
+        public boolean isRunning() {
+            int numFeatures = mFeatures.size();
+            if (mFeatures.isEmpty()) {
+                return false;
+            }
+
+            for (int i = 0; i < numFeatures; i++) {
+                if (mFeatures.valueAt(i).mRunning) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        /**
+         * @return The duration of the operation in milliseconds. The duration is in wall time.
+         */
+        public long getDuration() {
+            return getLastDuration(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+        }
+
+        /**
+         * Return the duration in milliseconds the app accessed this op while
+         * in the foreground. The duration is in wall time.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the foreground access duration in milliseconds.
+         *
+         * @see #getLastBackgroundDuration(int)
+         * @see #getLastDuration(int, int, int)
+         */
+        public long getLastForegroundDuration(@OpFlags int flags) {
+            return getSumOfFeatures((featureEntry) ->
+                    featureEntry.getLastForegroundDuration(flags));
+        }
+
+        /**
+         * Return the duration in milliseconds the app accessed this op while
+         * in the background. The duration is in wall time.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the background access duration in milliseconds.
+         *
+         * @see #getLastForegroundDuration(int)
+         * @see #getLastDuration(int, int, int)
+         */
+        public long getLastBackgroundDuration(@OpFlags int flags) {
+            return getSumOfFeatures((featureEntry) ->
+                    featureEntry.getLastBackgroundDuration(flags));
+        }
+
+        /**
+         * Return the duration in milliseconds the app accessed this op for
+         * a given range of UID states. The duration is in wall time.
+         *
+         * @param fromUidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state for which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the access duration in milliseconds.
+         */
+        public long getLastDuration(@UidState int fromUidState, @UidState int toUidState,
+                @OpFlags int flags) {
+            return getSumOfFeatures((featureEntry) ->
+                    featureEntry.getLastDuration(fromUidState, toUidState, flags));
+        }
+
+        /**
+         * Like {@link #findFirstNonNegativeForFlagsInStates(LongSparseLongArray, int, int, int)}
+         * but for all proxy uid in all features.
+         */
+        private long findFirstNonNegativeProxyUidInFeatureStates(@UidState int beginUidState,
+                @UidState int endUidState, @OpFlags int flags) {
+            int numFeatures = mFeatures.size();
+
+            if (numFeatures == 0) {
+                return -1;
+            }
+
+            while (flags != 0) {
+                final int flag = 1 << Integer.numberOfTrailingZeros(flags);
+                flags &= ~flag;
+                for (int uidState : UID_STATES) {
+                    if (uidState < beginUidState || uidState > endUidState) {
+                        continue;
+                    }
+
+                    final long key = makeKey(uidState, flag);
+
+                    for (int i = 0; i < numFeatures; i++) {
+                        OpFeatureEntry featureEntry = mFeatures.valueAt(i);
+
+                        if (featureEntry.mProxyUids == null) {
+                            continue;
+                        }
+
+                        final long proxyUid = featureEntry.mProxyUids.get(key);
+                        if (proxyUid >= 0) {
+                            return proxyUid;
+                        }
+                    }
+                }
+            }
+
+            return -1;
+        }
+
+        /**
+         * Like {@link #findFirstNonNullForFlagsInStates(LongSparseArray, int, int, int)} but
+         * for all proxyPackageNames in all features.
+         */
+        private @Nullable String findFirstNonNullProxyPackageNameInFeatureStates(
+                @OpFlags int flags, @UidState int beginUidState, @UidState int endUidState) {
+            int numFeatures = mFeatures.size();
+
+            if (numFeatures == 0) {
+                return null;
+            }
+
+            while (flags != 0) {
+                final int flag = 1 << Integer.numberOfTrailingZeros(flags);
+                flags &= ~flag;
+                for (int uidState : UID_STATES) {
+                    if (uidState < beginUidState || uidState > endUidState) {
+                        continue;
+                    }
+                    final long key = makeKey(uidState, flag);
+
+                    for (int i = 0; i < numFeatures; i++) {
+                        OpFeatureEntry featureEntry = mFeatures.valueAt(i);
+
+                        if (featureEntry.mProxyPackageNames == null) {
+                            continue;
+                        }
+
+                        final String proxyName = featureEntry.mProxyPackageNames.get(key);
+                        if (proxyName != null) {
+                            return proxyName;
+                        }
+                    }
+                }
+            }
+            return null;
+        }
+
+        /**
+         * @deprecated Use {@link #getProxyUid(int, int)} instead
+         */
+        @Deprecated
+        public int getProxyUid() {
+            return (int) findFirstNonNegativeProxyUidInFeatureStates(MAX_PRIORITY_UID_STATE,
+                    MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+        }
+
+        /**
+         * Gets the UID of the app that performed the op on behalf of this app and
+         * as a result blamed the op on this app or {@link Process#INVALID_UID} if
+         * there is no proxy.
+         *
+         * @param uidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         *
+         * @return The proxy UID.
+         */
+        public int getProxyUid(@UidState int uidState, @OpFlags int flags) {
+            return (int) findFirstNonNegativeProxyUidInFeatureStates(uidState, uidState, flags);
+        }
+
+        /**
+         * @deprecated Use {@link #getProxyPackageName(int, int)} instead
+         */
+        @Deprecated
+        public @Nullable String getProxyPackageName() {
+            return findFirstNonNullProxyPackageNameInFeatureStates(MAX_PRIORITY_UID_STATE,
+                    MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+        }
+
+        /**
+         * Gets the package name of the app that performed the op on behalf of this
+         * app and as a result blamed the op on this app for a UID state or
+         * {@code null} if there is no proxy.
+         *
+         * @param uidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return The proxy package name.
+         */
+        public @Nullable String getProxyPackageName(@UidState int uidState, @OpFlags int flags) {
+            return findFirstNonNullProxyPackageNameInFeatureStates(uidState, uidState, flags);
+        }
+
+        /**
+         * Create OpEntry from parcel.
+         *
+         * @hide
+         */
+        public static OpEntry createFromParcel(@NonNull Parcel source) {
+            int op = source.readInt();
+            int mode = source.readInt();
+
+            int numFeatures = source.readInt();
+            Pair<String, OpFeatureEntry.Builder>[] features = new Pair[numFeatures];
+            for (int i = 0; i < numFeatures; i++) {
+                features[i] = new Pair<>(source.readString(),
+                        OpFeatureEntry.createFromParcel(source));
+            }
+
+            return new OpEntry(op, mode, features);
+        }
+
         @Override
         public int describeContents() {
             return 0;
@@ -2751,31 +3372,23 @@
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(mOp);
             dest.writeInt(mMode);
-            dest.writeBoolean(mRunning);
-            writeLongSparseLongArrayToParcel(mAccessTimes, dest);
-            writeLongSparseLongArrayToParcel(mRejectTimes, dest);
-            writeLongSparseLongArrayToParcel(mDurations, dest);
-            writeLongSparseLongArrayToParcel(mProxyUids, dest);
-            writeLongSparseStringArrayToParcel(mProxyPackageNames, dest);
+
+            int numFeatures = mFeatures.size();
+            dest.writeInt(numFeatures);
+            for (int i = 0; i < numFeatures; i++) {
+                dest.writeString(mFeatures.keyAt(i));
+                mFeatures.valueAt(i).writeToParcel(dest, flags);
+            }
         }
 
-        OpEntry(Parcel source) {
-            mOp = source.readInt();
-            mMode = source.readInt();
-            mRunning = source.readBoolean();
-            mAccessTimes = readLongSparseLongArrayFromParcel(source);
-            mRejectTimes = readLongSparseLongArrayFromParcel(source);
-            mDurations = readLongSparseLongArrayFromParcel(source);
-            mProxyUids = readLongSparseLongArrayFromParcel(source);
-            mProxyPackageNames = readLongSparseStringArrayFromParcel(source);
-        }
-
-        public static final @android.annotation.NonNull Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
-            @Override public OpEntry createFromParcel(Parcel source) {
-                return new OpEntry(source);
+        public static final @NonNull Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
+            @Override
+            public @NonNull OpEntry createFromParcel(@NonNull Parcel parcel) {
+                return OpEntry.createFromParcel(parcel);
             }
 
-            @Override public OpEntry[] newArray(int size) {
+            @Override
+            public @NonNull OpEntry[] newArray(int size) {
                 return new OpEntry[size];
             }
         };
@@ -4428,7 +5041,7 @@
      * state due to UID policy or because it's controlled by a different master op.
      *
      * Use {@link #unsafeCheckOp(String, int, String)}} or
-     * {@link #noteOp(String, int, String, String)} if the effective mode is needed.
+     * {@link #noteOp(String, int, String, String, String)} if the effective mode is needed.
      *
      * @param ops The set of operations you are interested in, or null if you want all of them.
      * @hide
@@ -4452,7 +5065,7 @@
      * state due to UID policy or because it's controlled by a different master op.
      *
      * Use {@link #unsafeCheckOp(String, int, String)}} or
-     * {@link #noteOp(String, int, String, String)} if the effective mode is needed.
+     * {@link #noteOp(String, int, String, String, String)} if the effective mode is needed.
      *
      * @param ops The set of operations you are interested in, or null if you want all of them.
      * @hide
@@ -4474,7 +5087,7 @@
      * state due to UID policy or because it's controlled by a different master op.
      *
      * Use {@link #unsafeCheckOp(String, int, String)}} or
-     * {@link #noteOp(String, int, String, String)} if the effective mode is needed.
+     * {@link #noteOp(String, int, String, String, String)} if the effective mode is needed.
      *
      * @param uid The uid of the application of interest.
      * @param packageName The name of the application of interest.
@@ -4507,7 +5120,7 @@
      * state due to UID policy or because it's controlled by a different master op.
      *
      * Use {@link #unsafeCheckOp(String, int, String)}} or
-     * {@link #noteOp(String, int, String, String)} if the effective mode is needed.
+     * {@link #noteOp(String, int, String, String, String)} if the effective mode is needed.
      *
      * @param uid The uid of the application of interest.
      * @param packageName The name of the application of interest.
@@ -4897,8 +5510,8 @@
      *
      * @see #isOperationActive
      * @see #stopWatchingActive
-     * @see #startOp(int, int, String, boolean, String)
-     * @see #finishOp(int, int, String)
+     * @see #startOp(int, int, String, boolean, String, String)
+     * @see #finishOp(int, int, String, String)
      */
     // TODO: Uncomment below annotation once b/73559440 is fixed
     // @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
@@ -4948,8 +5561,8 @@
      *
      * @see #isOperationActive
      * @see #startWatchingActive
-     * @see #startOp(int, int, String, boolean, String)
-     * @see #finishOp(int, int, String)
+     * @see #startOp(int, int, String, boolean, String, String)
+     * @see #finishOp(int, int, String, String)
      */
     public void stopWatchingActive(@NonNull OnOpActiveChangedListener callback) {
         synchronized (mActiveWatchers) {
@@ -4979,7 +5592,7 @@
      *
      * @see #startWatchingActive(int[], OnOpActiveChangedListener)
      * @see #stopWatchingNoted(OnOpNotedListener)
-     * @see #noteOp(String, int, String, String)
+     * @see #noteOp(String, int, String, String, String)
      *
      * @hide
      */
@@ -5011,7 +5624,7 @@
      * Unregistering a non-registered callback has no effect.
      *
      * @see #startWatchingNoted(int[], OnOpNotedListener)
-     * @see #noteOp(String, int, String, String)
+     * @see #noteOp(String, int, String, String, String)
      *
      * @hide
      */
@@ -5047,15 +5660,15 @@
     /**
      * Do a quick check for whether an application might be able to perform an operation.
      * This is <em>not</em> a security check; you must use {@link #noteOp(String, int, String,
-     * String)} or {@link #startOp(String, int, String, String)} for your actual security checks,
-     * which also ensure that the given uid and package name are consistent. This function can just
-     * be used for a quick check to see if an operation has been disabled for the application,
-     * as an early reject of some work.  This does not modify the time stamp or other data
-     * about the operation.
+     * String, String)} or {@link #startOp(String, int, String, String, String)} for your actual
+     * security checks, which also ensure that the given uid and package name are consistent. This
+     * function can just be used for a quick check to see if an operation has been disabled for the
+     * application, as an early reject of some work.  This does not modify the time stamp or other
+     * data about the operation.
      *
      * <p>Important things this will not do (which you need to ultimate use
-     * {@link #noteOp(String, int, String, String)} or
-     * {@link #startOp(String, int, String, String)} to cover):</p>
+     * {@link #noteOp(String, int, String, String, String)} or
+     * {@link #startOp(String, int, String, String, String)} to cover):</p>
      * <ul>
      *     <li>Verifying the uid and package are consistent, so callers can't spoof
      *     their identity.</li>
@@ -5126,35 +5739,37 @@
     }
 
     /**
-     * @deprecated Use {@link #noteOp(String, int, String, String)} instead
+     * @deprecated Use {@link #noteOp(String, int, String, String, String)} instead
      */
     @Deprecated
     public int noteOp(@NonNull String op, int uid, @NonNull String packageName) {
-        return noteOp(op, uid, packageName, null);
+        return noteOp(op, uid, packageName, null, null);
     }
 
     /**
-     * @deprecated Use {@link #noteOp(String, int, String, String)} instead
+     * @deprecated Use {@link #noteOp(String, int, String, String, String)} instead
      *
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
-            + "#noteOp(java.lang.String, int, java.lang.String, java.lang.String)} instead")
+            + "#noteOp(java.lang.String, int, java.lang.String, java.lang.String, "
+            + "java.lang.String)} instead")
     @Deprecated
     public int noteOp(int op) {
-        return noteOp(op, Process.myUid(), mContext.getOpPackageName(), null);
+        return noteOp(op, Process.myUid(), mContext.getOpPackageName(), null, null);
     }
 
     /**
-     * @deprecated Use {@link #noteOp(String, int, String, String)} instead
+     * @deprecated Use {@link #noteOp(String, int, String, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
-            + "#noteOp(java.lang.String, int, java.lang.String, java.lang.String)} instead")
+            + "#noteOp(java.lang.String, int, java.lang.String, java.lang.String, "
+            + "java.lang.String)} instead")
     public int noteOp(int op, int uid, @Nullable String packageName) {
-        return noteOp(op, uid, packageName, null);
+        return noteOp(op, uid, packageName, null, null);
     }
 
     /**
@@ -5167,6 +5782,7 @@
      * @param op The operation to note.  One of the OPSTR_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param message A message describing the reason the op was noted
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -5176,8 +5792,8 @@
      * @throws SecurityException If the app has been configured to crash on this op.
      */
     public int noteOp(@NonNull String op, int uid, @Nullable String packageName,
-            @Nullable String message) {
-        return noteOp(strOpToOp(op), uid, packageName, message);
+            @Nullable String featureId, @Nullable String message) {
+        return noteOp(strOpToOp(op), uid, packageName, featureId, message);
     }
 
     /**
@@ -5190,6 +5806,7 @@
      * @param op The operation to note.  One of the OP_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param message A message describing the reason the op was noted
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -5200,8 +5817,9 @@
      *
      * @hide
      */
-    public int noteOp(int op, int uid, @Nullable String packageName, @Nullable String message) {
-        final int mode = noteOpNoThrow(op, uid, packageName, message);
+    public int noteOp(int op, int uid, @Nullable String packageName, @Nullable String featureId,
+            @Nullable String message) {
+        final int mode = noteOpNoThrow(op, uid, packageName, featureId, message);
         if (mode == MODE_ERRORED) {
             throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
         }
@@ -5209,27 +5827,28 @@
     }
 
     /**
-     * @deprecated Use {@link #noteOpNoThrow(String, int, String, String)} instead
+     * @deprecated Use {@link #noteOpNoThrow(String, int, String, String, String)} instead
      */
     @Deprecated
     public int noteOpNoThrow(@NonNull String op, int uid, @NonNull String packageName) {
-        return noteOpNoThrow(op, uid, packageName, null);
+        return noteOpNoThrow(op, uid, packageName, null, null);
     }
 
     /**
-     * @deprecated Use {@link #noteOpNoThrow(int, int, String, String)} instead
+     * @deprecated Use {@link #noteOpNoThrow(int, int, String, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
-            + "#noteOpNoThrow(java.lang.String, int, java.lang.String, java.lang.String)} instead")
+            + "#noteOpNoThrow(java.lang.String, int, java.lang.String, java.lang.String, "
+            + "java.lang.String)} instead")
     public int noteOpNoThrow(int op, int uid, String packageName) {
-        return noteOpNoThrow(op, uid, packageName, null);
+        return noteOpNoThrow(op, uid, packageName, null, null);
     }
 
     /**
-     * Like {@link #noteOp(String, int, String, String)} but instead of throwing a
+     * Like {@link #noteOp(String, int, String, String, String)} but instead of throwing a
      * {@link SecurityException} it returns {@link #MODE_ERRORED}.
      *
      * @param op The operation to note.  One of the OPSTR_* constants.
@@ -5242,17 +5861,18 @@
      * causing the app to crash).
      */
     public int noteOpNoThrow(@NonNull String op, int uid, @NonNull String packageName,
-            @Nullable String message) {
-        return noteOpNoThrow(strOpToOp(op), uid, packageName, message);
+            @Nullable String feature, @Nullable String message) {
+        return noteOpNoThrow(strOpToOp(op), uid, packageName, feature, message);
     }
 
     /**
-     * Like {@link #noteOp(String, int, String, String)} but instead of throwing a
+     * Like {@link #noteOp(String, int, String, String, String)} but instead of throwing a
      * {@link SecurityException} it returns {@link #MODE_ERRORED}.
      *
      * @param op The operation to note.  One of the OP_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param message A message describing the reason the op was noted
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -5262,11 +5882,11 @@
      * @hide
      */
     public int noteOpNoThrow(int op, int uid, @Nullable String packageName,
-            @Nullable String message) {
+            @Nullable String featureId, @Nullable String message) {
         try {
-            int mode = mService.noteOperation(op, uid, packageName);
+            int mode = mService.noteOperation(op, uid, packageName, featureId);
             if (mode == MODE_ALLOWED) {
-                markAppOpNoted(uid, packageName, op, message);
+                markAppOpNoted(uid, packageName, op, featureId, message);
             }
 
             return mode;
@@ -5276,23 +5896,24 @@
     }
 
     /**
-     * @deprecated Use {@link #noteProxyOp(String, String, int, String)} instead
+     * @deprecated Use {@link #noteProxyOp(String, String, int, String, String)} instead
      */
     @Deprecated
     public int noteProxyOp(@NonNull String op, @NonNull String proxiedPackageName) {
-        return noteProxyOp(op, proxiedPackageName, Binder.getCallingUid(), null);
+        return noteProxyOp(op, proxiedPackageName, Binder.getCallingUid(), null, null);
     }
 
     /**
-     * @deprecated Use {@link #noteProxyOp(String, String, int, String)} instead
+     * @deprecated Use {@link #noteProxyOp(String, String, int, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
-            + "#noteProxyOp(java.lang.String, java.lang.String, int, java.lang.String)} instead")
+            + "#noteProxyOp(java.lang.String, java.lang.String, int, java.lang.String, "
+            + "java.lang.String)} instead")
     public int noteProxyOp(int op, @Nullable String proxiedPackageName) {
-        return noteProxyOp(op, proxiedPackageName, Binder.getCallingUid(), null);
+        return noteProxyOp(op, proxiedPackageName, Binder.getCallingUid(), null, null);
     }
 
     /**
@@ -5304,6 +5925,8 @@
      * @param op The operation to note. One of the OP_* constants.
      * @param proxiedPackageName The name of the application calling into the proxy application.
      * @param proxiedUid The uid of the proxied application
+     * @param proxiedFeatureId The feature in the proxied app or {@code null} for default
+     *                           feature
      * @param message A message describing the reason the op was noted
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or {@link #MODE_IGNORED}
@@ -5315,8 +5938,9 @@
      * @hide
      */
     public int noteProxyOp(int op, @Nullable String proxiedPackageName, int proxiedUid,
-            @Nullable String message) {
-        int mode = noteProxyOpNoThrow(op, proxiedPackageName, proxiedUid, message);
+            @Nullable String proxiedFeatureId, @Nullable String message) {
+        int mode = noteProxyOpNoThrow(op, proxiedPackageName, proxiedUid, proxiedFeatureId,
+                message);
         if (mode == MODE_ERRORED) {
             throw new SecurityException("Proxy package " + mContext.getOpPackageName()
                     + " from uid " + Process.myUid() + " or calling package " + proxiedPackageName
@@ -5334,6 +5958,8 @@
      * @param op The operation to note. One of the OPSTR_* constants.
      * @param proxiedPackageName The name of the application calling into the proxy application.
      * @param proxiedUid The uid of the proxied application
+     * @param proxiedFeatureId The feature in the proxied app or {@code null} for default
+     *                           feature
      * @param message A message describing the reason the op was noted
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or {@link #MODE_IGNORED}
@@ -5343,29 +5969,30 @@
      * op.
      */
     public int noteProxyOp(@NonNull String op, @Nullable String proxiedPackageName, int proxiedUid,
-            @Nullable String message) {
-        return noteProxyOp(strOpToOp(op), proxiedPackageName, proxiedUid, message);
+            @Nullable String proxiedFeatureId, @Nullable String message) {
+        return noteProxyOp(strOpToOp(op), proxiedPackageName, proxiedUid, proxiedFeatureId,
+                message);
     }
 
     /**
-     * @deprecated Use {@link #noteProxyOpNoThrow(String, String, int, String)} instead
+     * @deprecated Use {@link #noteProxyOpNoThrow(String, String, int, String, String)} instead
      */
     @Deprecated
     public int noteProxyOpNoThrow(@NonNull String op, @NonNull String proxiedPackageName) {
-        return noteProxyOpNoThrow(op, proxiedPackageName, Binder.getCallingUid(), null);
+        return noteProxyOpNoThrow(op, proxiedPackageName, Binder.getCallingUid(), null, null);
     }
 
     /**
-     * @deprecated Use {@link #noteProxyOpNoThrow(String, String, int, String)} instead
+     * @deprecated Use {@link #noteProxyOpNoThrow(String, String, int, String, String)} instead
      */
     @Deprecated
     public int noteProxyOpNoThrow(@NonNull String op, @Nullable String proxiedPackageName,
             int proxiedUid) {
-        return noteProxyOpNoThrow(op, proxiedPackageName, proxiedUid, null);
+        return noteProxyOpNoThrow(op, proxiedPackageName, proxiedUid, null, null);
     }
 
     /**
-     * Like {@link #noteProxyOp(String, String, int, String)} but instead
+     * Like {@link #noteProxyOp(String, String, int, String, String)} but instead
      * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
      *
      * <p>This API requires package with the {@code proxiedPackageName} to belong to
@@ -5374,37 +6001,43 @@
      * @param op The op to note
      * @param proxiedPackageName The package to note the op for
      * @param proxiedUid The uid the package belongs to
+     * @param proxiedFeatureId The feature in the proxied app or {@code null} for default
+     *                           feature
      * @param message A message describing the reason the op was noted
      */
     public int noteProxyOpNoThrow(@NonNull String op, @Nullable String proxiedPackageName,
-            int proxiedUid, @Nullable String message) {
-        return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName, proxiedUid, message);
+            int proxiedUid, @Nullable String proxiedFeatureId, @Nullable String message) {
+        return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName, proxiedUid,
+                proxiedFeatureId, message);
     }
 
     /**
-     * Like {@link #noteProxyOp(int, String, int, String)} but instead
+     * Like {@link #noteProxyOp(int, String, int, String, String)} but instead
      * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
      *
      * @param op The op to note
      * @param proxiedPackageName The package to note the op for or {@code null} if the op should be
      *                           noted for the "android" package
      * @param proxiedUid The uid the package belongs to
+     * @param proxiedFeatureId The feature in the proxied app or {@code null} for default
+     *                           feature
      * @param message A message describing the reason the op was noted
      *
      * @hide
      */
     public int noteProxyOpNoThrow(int op, @Nullable String proxiedPackageName, int proxiedUid,
-            @Nullable String message) {
+            @Nullable String proxiedFeatureId, @Nullable String message) {
         int myUid = Process.myUid();
 
         try {
-            int mode = mService.noteProxyOperation(op, myUid, mContext.getOpPackageName(),
-                    proxiedUid, proxiedPackageName);
+            int mode = mService.noteProxyOperation(op, proxiedUid, proxiedPackageName,
+                    proxiedFeatureId, myUid, mContext.getOpPackageName(),
+                    mContext.getFeatureId());
             if (mode == MODE_ALLOWED
                     // Only collect app-ops when the proxy is trusted
                     && mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1, myUid)
                     == PackageManager.PERMISSION_GRANTED) {
-                markAppOpNoted(proxiedUid, proxiedPackageName, op, message);
+                markAppOpNoted(proxiedUid, proxiedPackageName, op, proxiedFeatureId, message);
             }
 
             return mode;
@@ -5416,15 +6049,15 @@
     /**
      * Do a quick check for whether an application might be able to perform an operation.
      * This is <em>not</em> a security check; you must use {@link #noteOp(String, int, String,
-     * String)} or {@link #startOp(int, int, String, boolean, String)} for your actual security
-     * checks, which also ensure that the given uid and package name are consistent. This function
-     * can just be used for a quick check to see if an operation has been disabled for the
-     * application, as an early reject of some work.  This does not modify the time stamp or other
-     * data about the operation.
+     * String, String)} or {@link #startOp(int, int, String, boolean, String, String)} for your
+     * actual security checks, which also ensure that the given uid and package name are consistent.
+     * This function can just be used for a quick check to see if an operation has been disabled for
+     * the application, as an early reject of some work.  This does not modify the time stamp or
+     * other data about the operation.
      *
      * <p>Important things this will not do (which you need to ultimate use
-     * {@link #noteOp(String, int, String, String)} or
-     * {@link #startOp(int, int, String, boolean, String)} to cover):</p>
+     * {@link #noteOp(String, int, String, String, String)} or
+     * {@link #startOp(int, int, String, boolean, String, String)} to cover):</p>
      * <ul>
      *     <li>Verifying the uid and package are consistent, so callers can't spoof
      *     their identity.</li>
@@ -5534,41 +6167,41 @@
 
 
     /**
-     * @deprecated use {@link #startOp(String, int, String, String)} instead
+     * @deprecated use {@link #startOp(String, int, String, String, String)} instead
      */
     @Deprecated
     public int startOp(@NonNull String op, int uid, @NonNull String packageName) {
-        return startOp(op, uid, packageName, null);
+        return startOp(op, uid, packageName, null, null);
     }
 
     /**
-     * @deprecated Use {@link #startOp(int, int, String, boolean, String)} instead
+     * @deprecated Use {@link #startOp(int, int, String, boolean, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     public int startOp(int op) {
-        return startOp(op, Process.myUid(), mContext.getOpPackageName(), false, null);
+        return startOp(op, Process.myUid(), mContext.getOpPackageName(), false, null, null);
     }
 
     /**
-     * @deprecated Use {@link #startOp(int, int, String, boolean, String)} instead
+     * @deprecated Use {@link #startOp(int, int, String, boolean, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     public int startOp(int op, int uid, String packageName) {
-        return startOp(op, uid, packageName, false, null);
+        return startOp(op, uid, packageName, false, null, null);
     }
 
     /**
-     * @deprecated Use {@link #startOp(int, int, String, boolean, String)} instead
+     * @deprecated Use {@link #startOp(int, int, String, boolean, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     public int startOp(int op, int uid, String packageName, boolean startIfModeDefault) {
-        return startOp(op, uid, packageName, startIfModeDefault, null);
+        return startOp(op, uid, packageName, startIfModeDefault, null, null);
     }
 
     /**
@@ -5577,6 +6210,7 @@
      * @param op The operation to start.  One of the OPSTR_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param message Description why op was started
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -5587,8 +6221,8 @@
      * the package is not in the passed in UID.
      */
     public int startOp(@NonNull String op, int uid, @Nullable String packageName,
-            @Nullable String message) {
-        return startOp(strOpToOp(op), uid, packageName, false, message);
+            @NonNull String featureId, @Nullable String message) {
+        return startOp(strOpToOp(op), uid, packageName, false, featureId, message);
     }
 
     /**
@@ -5597,6 +6231,7 @@
      * @param op The operation to start.  One of the OP_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}.
      * @param message Description why op was started
      *
@@ -5610,8 +6245,9 @@
      * @hide
      */
     public int startOp(int op, int uid, @Nullable String packageName, boolean startIfModeDefault,
-            @Nullable String message) {
-        final int mode = startOpNoThrow(op, uid, packageName, startIfModeDefault, message);
+            @NonNull String featureId, @Nullable String message) {
+        final int mode = startOpNoThrow(op, uid, packageName, startIfModeDefault, featureId,
+                message);
         if (mode == MODE_ERRORED) {
             throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
         }
@@ -5619,40 +6255,41 @@
     }
 
     /**
-     * @deprecated use {@link #startOpNoThrow(String, int, String, String)} instead
+     * @deprecated use {@link #startOpNoThrow(String, int, String, String, String)} instead
      */
     @Deprecated
     public int startOpNoThrow(@NonNull String op, int uid, @NonNull String packageName) {
-        return startOpNoThrow(op, uid, packageName, null);
+        return startOpNoThrow(op, uid, packageName, null, null);
     }
 
     /**
-     * @deprecated Use {@link #startOpNoThrow(int, int, String, boolean, String} instead
+     * @deprecated Use {@link #startOpNoThrow(int, int, String, boolean, String, String} instead
      *
      * @hide
      */
     @Deprecated
     public int startOpNoThrow(int op, int uid, String packageName) {
-        return startOpNoThrow(op, uid, packageName, false, null);
+        return startOpNoThrow(op, uid, packageName, false, null, null);
     }
 
     /**
-     * @deprecated Use {@link #startOpNoThrow(int, int, String, boolean, String} instead
+     * @deprecated Use {@link #startOpNoThrow(int, int, String, boolean, String, String} instead
      *
      * @hide
      */
     @Deprecated
     public int startOpNoThrow(int op, int uid, String packageName, boolean startIfModeDefault) {
-        return startOpNoThrow(op, uid, packageName, startIfModeDefault, null);
+        return startOpNoThrow(op, uid, packageName, startIfModeDefault, null, null);
     }
 
     /**
-     * Like {@link #startOp(String, int, String, String)} but instead of throwing a
+     * Like {@link #startOp(String, int, String, String, String)} but instead of throwing a
      * {@link SecurityException} it returns {@link #MODE_ERRORED}.
      *
      * @param op The operation to start.  One of the OP_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param message Description why op was started
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -5660,17 +6297,18 @@
      * causing the app to crash).
      */
     public int startOpNoThrow(@NonNull String op, int uid, @NonNull String packageName,
-            @Nullable String message) {
-        return startOpNoThrow(strOpToOp(op), uid, packageName, false, message);
+            @NonNull String featureId, @Nullable String message) {
+        return startOpNoThrow(strOpToOp(op), uid, packageName, false, featureId, message);
     }
 
     /**
-     * Like {@link #startOp(int, int, String, boolean, String)} but instead of throwing a
+     * Like {@link #startOp(int, int, String, boolean, String, String)} but instead of throwing a
      * {@link SecurityException} it returns {@link #MODE_ERRORED}.
      *
      * @param op The operation to start.  One of the OP_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}.
      * @param message Description why op was started
      *
@@ -5681,12 +6319,12 @@
      * @hide
      */
     public int startOpNoThrow(int op, int uid, @NonNull String packageName,
-            boolean startIfModeDefault, @Nullable String message) {
+            boolean startIfModeDefault, @Nullable String featureId, @Nullable String message) {
         try {
             int mode = mService.startOperation(getToken(mService), op, uid, packageName,
-                    startIfModeDefault);
+                    featureId, startIfModeDefault);
             if (mode == MODE_ALLOWED) {
-                markAppOpNoted(uid, packageName, op, message);
+                markAppOpNoted(uid, packageName, op, featureId, message);
             }
 
             return mode;
@@ -5696,36 +6334,54 @@
     }
 
     /**
-     * @deprecated Use {@link #finishOp(String, int, String)} instead
+     * @deprecated Use {@link #finishOp(String, int, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     public void finishOp(int op) {
-        finishOp(op, Process.myUid(), mContext.getOpPackageName());
+        finishOp(op, Process.myUid(), mContext.getOpPackageName(), null);
     }
 
     /**
-     * Report that an application is no longer performing an operation that had previously
-     * been started with {@link #startOp(String, int, String, String)}.  There is no validation of
-     * input or result; the parameters supplied here must be the exact same ones previously passed
-     * in when starting the operation.
+     * @deprecated Use {@link #finishOp(String, int, String, String)} instead
      */
     public void finishOp(@NonNull String op, int uid, @NonNull String packageName) {
-        finishOp(strOpToOp(op), uid, packageName);
+        finishOp(strOpToOp(op), uid, packageName, null);
     }
 
     /**
      * Report that an application is no longer performing an operation that had previously
-     * been started with {@link #startOp(int, int, String, boolean, String)}. There is no
+     * been started with {@link #startOp(String, int, String, String, String)}.  There is no
+     * validation of input or result; the parameters supplied here must be the exact same ones
+     * previously passed in when starting the operation.
+     */
+    public void finishOp(@NonNull String op, int uid, @NonNull String packageName,
+            @Nullable String featureId) {
+        finishOp(strOpToOp(op), uid, packageName, featureId);
+    }
+
+    /**
+     * @deprecated Use {@link #finishOp(int, int, String, String)} instead
+     *
+     * @hide
+     */
+    public void finishOp(int op, int uid, @NonNull String packageName) {
+        finishOp(op, uid, packageName, null);
+    }
+
+    /**
+     * Report that an application is no longer performing an operation that had previously
+     * been started with {@link #startOp(int, int, String, boolean, String, String)}. There is no
      * validation of input or result; the parameters supplied here must be the exact same ones
      * previously passed in when starting the operation.
      *
      * @hide
      */
-    public void finishOp(int op, int uid, @NonNull String packageName) {
+    public void finishOp(int op, int uid, @NonNull String packageName,
+            @Nullable String featureId) {
         try {
-            mService.finishOperation(getToken(mService), op, uid, packageName);
+            mService.finishOperation(getToken(mService), op, uid, packageName, featureId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -5737,8 +6393,8 @@
      * If you don't hold the {@code android.Manifest.permission#WATCH_APPOPS}
      * permission you can query only for your UID.
      *
-     * @see #finishOp(String, int, String)
-     * @see #startOp(String, int, String, String)
+     * @see #finishOp(String, int, String, String)
+     * @see #startOp(String, int, String, String, String)
      */
     public boolean isOpActive(@NonNull String op, int uid, @NonNull String packageName) {
         return isOperationActive(strOpToOp(op), uid, packageName);
@@ -5766,9 +6422,10 @@
      */
     public static class PausedNotedAppOpsCollection {
         final int mUid;
-        final @Nullable long[] mCollectedNotedAppOps;
+        final @Nullable ArrayMap<String, long[]> mCollectedNotedAppOps;
 
-        PausedNotedAppOpsCollection(int uid, @Nullable long[] collectedNotedAppOps) {
+        PausedNotedAppOpsCollection(int uid, @Nullable ArrayMap<String,
+                long[]> collectedNotedAppOps) {
             mUid = uid;
             mCollectedNotedAppOps = collectedNotedAppOps;
         }
@@ -5786,7 +6443,8 @@
     public static @Nullable PausedNotedAppOpsCollection pauseNotedAppOpsCollection() {
         Integer previousUid = sBinderThreadCallingUid.get();
         if (previousUid != null) {
-            long[] previousCollectedNotedAppOps = sAppOpsNotedInThisBinderTransaction.get();
+            ArrayMap<String, long[]> previousCollectedNotedAppOps =
+                    sAppOpsNotedInThisBinderTransaction.get();
 
             sBinderThreadCallingUid.remove();
             sAppOpsNotedInThisBinderTransaction.remove();
@@ -5832,8 +6490,12 @@
     /**
      * Mark an app-op as noted
      */
-    private void markAppOpNoted(int uid, @NonNull String packageName, int code,
-            @Nullable String message) {
+    private void markAppOpNoted(int uid, @Nullable String packageName, int code,
+            @Nullable String featureId, @Nullable String message) {
+        if (packageName == null) {
+            packageName = "android";
+        }
+
         // check it the appops needs to be collected and cache result
         if (sAppOpsToNote[code] == SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED) {
             boolean shouldCollectNotes;
@@ -5860,7 +6522,7 @@
             if (sNotedAppOpsCollector != null && uid == Process.myUid() && packageName.equals(
                     ActivityThread.currentOpPackageName())) {
                 // This app is noting an app-op for itself. Deliver immediately.
-                sNotedAppOpsCollector.onSelfNoted(new SyncNotedAppOp(code));
+                sNotedAppOpsCollector.onSelfNoted(new SyncNotedAppOp(code, featureId));
 
                 return;
             }
@@ -5869,18 +6531,24 @@
         if (binderUid != null && binderUid == uid) {
             // If this is inside of a two-way binder call: Delivered to caller via
             // {@link #prefixParcelWithAppOpsIfNeeded}
-            long[] appOpsNotedInThisBinderTransaction;
+            // We are inside of a two-way binder call. Delivered to caller via
+            // {@link #prefixParcelWithAppOpsIfNeeded}
+            ArrayMap<String, long[]> appOpsNoted = sAppOpsNotedInThisBinderTransaction.get();
+            if (appOpsNoted == null) {
+                appOpsNoted = new ArrayMap<>(1);
+                sAppOpsNotedInThisBinderTransaction.set(appOpsNoted);
+            }
 
-            appOpsNotedInThisBinderTransaction = sAppOpsNotedInThisBinderTransaction.get();
-            if (appOpsNotedInThisBinderTransaction == null) {
-                appOpsNotedInThisBinderTransaction = new long[2];
-                sAppOpsNotedInThisBinderTransaction.set(appOpsNotedInThisBinderTransaction);
+            long[] appOpsNotedForFeature = appOpsNoted.get(featureId);
+            if (appOpsNotedForFeature == null) {
+                appOpsNotedForFeature = new long[2];
+                appOpsNoted.put(featureId, appOpsNotedForFeature);
             }
 
             if (code < 64) {
-                appOpsNotedInThisBinderTransaction[0] |= 1L << code;
+                appOpsNotedForFeature[0] |= 1L << code;
             } else {
-                appOpsNotedInThisBinderTransaction[1] |= 1L << (code - 64);
+                appOpsNotedForFeature[1] |= 1L << (code - 64);
             }
         } else {
             // Cannot deliver the note synchronous: Hence send it to the system server to
@@ -5892,7 +6560,8 @@
 
             long token = Binder.clearCallingIdentity();
             try {
-                mService.noteAsyncOp(mContext.getOpPackageName(), uid, packageName, code, message);
+                mService.noteAsyncOp(mContext.getOpPackageName(), uid, packageName, code,
+                        featureId, message);
             } catch (RemoteException e) {
                 e.rethrowFromSystemServer();
             } finally {
@@ -5912,14 +6581,21 @@
      * @hide
      */
     public static void prefixParcelWithAppOpsIfNeeded(@NonNull Parcel p) {
-        long[] notedAppOps = sAppOpsNotedInThisBinderTransaction.get();
-        if (notedAppOps == null || (notedAppOps[0] == 0 && notedAppOps[1] == 0)) {
+        ArrayMap<String, long[]> notedAppOps = sAppOpsNotedInThisBinderTransaction.get();
+        if (notedAppOps == null) {
             return;
         }
 
         p.writeInt(Parcel.EX_HAS_NOTED_APPOPS_REPLY_HEADER);
-        p.writeLong(notedAppOps[0]);
-        p.writeLong(notedAppOps[1]);
+
+        int numFeatureWithNotesAppOps = notedAppOps.size();
+        p.writeInt(numFeatureWithNotesAppOps);
+
+        for (int i = 0; i < numFeatureWithNotesAppOps; i++) {
+            p.writeString(notedAppOps.keyAt(i));
+            p.writeLong(notedAppOps.valueAt(i)[0]);
+            p.writeLong(notedAppOps.valueAt(i)[1]);
+        }
     }
 
     /**
@@ -5928,26 +6604,28 @@
      * <p>This is called on the calling side of a two way binder transaction just after the
      * transaction returns.
      *
-     * <p>Note: Make sure to keep frameworks/native/libs/binder/Status.cpp::readAndLogNotedAppops
-     * in sync.
-     *
      * @param p The parcel to read from
      *
      * @hide
      */
     public static void readAndLogNotedAppops(@NonNull Parcel p) {
-        long[] rawNotedAppOps = new long[2];
-        rawNotedAppOps[0] = p.readLong();
-        rawNotedAppOps[1] = p.readLong();
+        int numFeaturesWithNotedAppOps = p.readInt();
 
-        if (rawNotedAppOps[0] != 0 || rawNotedAppOps[1] != 0) {
-            BitSet notedAppOps = BitSet.valueOf(rawNotedAppOps);
+        for (int i = 0; i < numFeaturesWithNotedAppOps; i++) {
+            String featureId = p.readString();
+            long[] rawNotedAppOps = new long[2];
+            rawNotedAppOps[0] = p.readLong();
+            rawNotedAppOps[1] = p.readLong();
 
-            synchronized (sLock) {
-                for (int code = notedAppOps.nextSetBit(0); code != -1;
-                        code = notedAppOps.nextSetBit(code + 1)) {
-                    if (sNotedAppOpsCollector != null) {
-                        sNotedAppOpsCollector.onNoted(new SyncNotedAppOp(code));
+            if (rawNotedAppOps[0] != 0 || rawNotedAppOps[1] != 0) {
+                BitSet notedAppOps = BitSet.valueOf(rawNotedAppOps);
+
+                synchronized (sLock) {
+                    for (int code = notedAppOps.nextSetBit(0); code != -1;
+                            code = notedAppOps.nextSetBit(code + 1)) {
+                        if (sNotedAppOpsCollector != null) {
+                            sNotedAppOpsCollector.onNoted(new SyncNotedAppOp(code, featureId));
+                        }
                     }
                 }
             }
@@ -6134,8 +6812,8 @@
      *
      * @see #startWatchingActive(int[], OnOpActiveChangedListener)
      * @see #stopWatchingMode(OnOpChangedListener)
-     * @see #finishOp(int)
-     * @see #startOp(int, int, String, boolean, String)
+     * @see #finishOp(int, int, String, String)
+     * @see #startOp(int, int, String, boolean, String, String)
      *
      * @hide */
     @TestApi
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 19be6c9..bd7ef2a 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -16,10 +16,11 @@
 
 package android.app;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.util.SparseIntArray;
 
 import com.android.internal.util.function.QuadFunction;
-import com.android.internal.util.function.TriFunction;
 
 /**
  * App ops service local interface.
@@ -60,12 +61,14 @@
          *
          * @param code The op code to note.
          * @param uid The UID for which to note.
-         * @param packageName The package for which to note.
+         * @param packageName The package for which to note. {@code null} for system package.
+         * @param featureId Id of the feature in the package
          * @param superImpl The super implementation.
          * @return The app op note result.
          */
-        int noteOperation(int code, int uid, String packageName,
-                TriFunction<Integer, Integer, String, Integer> superImpl);
+        int noteOperation(int code, int uid, @Nullable String packageName,
+                @Nullable String featureId,
+                @NonNull QuadFunction<Integer, Integer, String, String, Integer> superImpl);
     }
 
     /**
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 86bf20a..03ef286 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -3160,6 +3160,15 @@
     }
 
     @Override
+    public String[] getTelephonyPackageNames() {
+        try {
+            return mPM.getTelephonyPackageNames();
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    @Override
     public String getSystemCaptionsServicePackageName() {
         try {
             return mPM.getSystemCaptionsServicePackageName();
diff --git a/core/java/android/app/AsyncNotedAppOp.java b/core/java/android/app/AsyncNotedAppOp.java
index df6533a..958ebae 100644
--- a/core/java/android/app/AsyncNotedAppOp.java
+++ b/core/java/android/app/AsyncNotedAppOp.java
@@ -25,7 +25,7 @@
 import com.android.internal.util.DataClass;
 
 /**
- * When an {@link AppOpsManager#noteOp(String, int, String, String) app-op is noted} and the
+ * When an {@link AppOpsManager#noteOp(String, int, String, String, String) app-op is noted} and the
  * app the app-op is noted for has a {@link AppOpsManager.AppOpsCollector} registered the note-event
  * needs to be delivered to the collector. Usually this is done via an {@link SyncNotedAppOp}, but
  * in some cases this is not possible. In this case an {@link AsyncNotedAppOp} is send to the system
@@ -51,6 +51,9 @@
      */
     private final @Nullable String mNotingPackageName;
 
+    /** {@link android.content.Context#createFeatureContext Feature} in the app */
+    private final @Nullable String mFeatureId;
+
     /** Message associated with the noteOp. This message is set by the app noting the op */
     private final @NonNull String mMessage;
 
@@ -66,14 +69,18 @@
 
 
 
-    // Code below generated by codegen v1.0.0.
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
     // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/app/AsyncNotedAppOp.java
     //
-    // CHECKSTYLE:OFF Generated code
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
 
     /**
      * Creates a new AsyncNotedAppOp.
@@ -83,7 +90,10 @@
      * @param notingUid
      *   Uid that noted the op
      * @param notingPackageName
-     *   Package that noted the op
+     *   Package that noted the op. {@code null} if the package name that noted the op could be not
+     *   be determined (e.g. when the op is noted from native code).
+     * @param featureId
+     *   {@link android.content.Context#createFeatureContext Feature} in the app
      * @param message
      *   Message associated with the noteOp. This message is set by the app noting the op
      * @param time
@@ -95,6 +105,7 @@
             @IntRange(from = 0, to = AppOpsManager._NUM_OP - 1) int opCode,
             @IntRange(from = 0) int notingUid,
             @Nullable String notingPackageName,
+            @Nullable String featureId,
             @NonNull String message,
             @IntRange(from = 0) long time) {
         this.mOpCode = opCode;
@@ -107,6 +118,7 @@
                 IntRange.class, null, mNotingUid,
                 "from", 0);
         this.mNotingPackageName = notingPackageName;
+        this.mFeatureId = featureId;
         this.mMessage = message;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mMessage);
@@ -127,7 +139,8 @@
     }
 
     /**
-     * Package that noted the op
+     * Package that noted the op. {@code null} if the package name that noted the op could be not
+     * be determined (e.g. when the op is noted from native code).
      */
     @DataClass.Generated.Member
     public @Nullable String getNotingPackageName() {
@@ -135,6 +148,14 @@
     }
 
     /**
+     * {@link android.content.Context#createFeatureContext Feature} in the app
+     */
+    @DataClass.Generated.Member
+    public @Nullable String getFeatureId() {
+        return mFeatureId;
+    }
+
+    /**
      * Message associated with the noteOp. This message is set by the app noting the op
      */
     @DataClass.Generated.Member
@@ -152,7 +173,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public boolean equals(Object o) {
+    public boolean equals(@Nullable Object o) {
         // You can override field equality logic by defining either of the methods like:
         // boolean fieldNameEquals(AsyncNotedAppOp other) { ... }
         // boolean fieldNameEquals(FieldType otherValue) { ... }
@@ -166,6 +187,7 @@
                 && mOpCode == that.mOpCode
                 && mNotingUid == that.mNotingUid
                 && java.util.Objects.equals(mNotingPackageName, that.mNotingPackageName)
+                && java.util.Objects.equals(mFeatureId, that.mFeatureId)
                 && java.util.Objects.equals(mMessage, that.mMessage)
                 && mTime == that.mTime;
     }
@@ -180,6 +202,7 @@
         _hash = 31 * _hash + mOpCode;
         _hash = 31 * _hash + mNotingUid;
         _hash = 31 * _hash + java.util.Objects.hashCode(mNotingPackageName);
+        _hash = 31 * _hash + java.util.Objects.hashCode(mFeatureId);
         _hash = 31 * _hash + java.util.Objects.hashCode(mMessage);
         _hash = 31 * _hash + Long.hashCode(mTime);
         return _hash;
@@ -187,16 +210,18 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(android.os.Parcel dest, int flags) {
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
         byte flg = 0;
         if (mNotingPackageName != null) flg |= 0x4;
+        if (mFeatureId != null) flg |= 0x8;
         dest.writeByte(flg);
         dest.writeInt(mOpCode);
         dest.writeInt(mNotingUid);
         if (mNotingPackageName != null) dest.writeString(mNotingPackageName);
+        if (mFeatureId != null) dest.writeString(mFeatureId);
         dest.writeString(mMessage);
         dest.writeLong(mTime);
     }
@@ -205,6 +230,43 @@
     @DataClass.Generated.Member
     public int describeContents() { return 0; }
 
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ AsyncNotedAppOp(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        int opCode = in.readInt();
+        int notingUid = in.readInt();
+        String notingPackageName = (flg & 0x4) == 0 ? null : in.readString();
+        String featureId = (flg & 0x8) == 0 ? null : in.readString();
+        String message = in.readString();
+        long time = in.readLong();
+
+        this.mOpCode = opCode;
+        com.android.internal.util.AnnotationValidations.validate(
+                IntRange.class, null, mOpCode,
+                "from", 0,
+                "to", AppOpsManager._NUM_OP - 1);
+        this.mNotingUid = notingUid;
+        com.android.internal.util.AnnotationValidations.validate(
+                IntRange.class, null, mNotingUid,
+                "from", 0);
+        this.mNotingPackageName = notingPackageName;
+        this.mFeatureId = featureId;
+        this.mMessage = message;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mMessage);
+        this.mTime = time;
+        com.android.internal.util.AnnotationValidations.validate(
+                IntRange.class, null, mTime,
+                "from", 0);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
     @DataClass.Generated.Member
     public static final @NonNull Parcelable.Creator<AsyncNotedAppOp> CREATOR
             = new Parcelable.Creator<AsyncNotedAppOp>() {
@@ -214,31 +276,16 @@
         }
 
         @Override
-        @SuppressWarnings({"unchecked", "RedundantCast"})
-        public AsyncNotedAppOp createFromParcel(android.os.Parcel in) {
-            // You can override field unparcelling by defining methods like:
-            // static FieldType unparcelFieldName(Parcel in) { ... }
-
-            byte flg = in.readByte();
-            int opCode = in.readInt();
-            int notingUid = in.readInt();
-            String notingPackageName = (flg & 0x4) == 0 ? null : in.readString();
-            String message = in.readString();
-            long time = in.readLong();
-            return new AsyncNotedAppOp(
-                    opCode,
-                    notingUid,
-                    notingPackageName,
-                    message,
-                    time);
+        public AsyncNotedAppOp createFromParcel(@NonNull android.os.Parcel in) {
+            return new AsyncNotedAppOp(in);
         }
     };
 
     @DataClass.Generated(
-            time = 1566503083973L,
-            codegenVersion = "1.0.0",
+            time = 1571327470155L,
+            codegenVersion = "1.0.9",
             sourceFile = "frameworks/base/core/java/android/app/AsyncNotedAppOp.java",
-            inputSignatures = "private final @android.annotation.IntRange(from=0L, to=91L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mNotingPackageName\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
+            inputSignatures = "private final @android.annotation.IntRange(from=0L, to=91L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mNotingPackageName\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 39fab63..eb2b2bc 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -204,6 +204,9 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final String mOpPackageName;
 
+    /** If of feature this context is for */
+    private final @Nullable String mFeatureId;
+
     private final @NonNull ResourcesManager mResourcesManager;
     @UnsupportedAppUsage
     private @NonNull Resources mResources;
@@ -395,6 +398,12 @@
         return mOpPackageName != null ? mOpPackageName : getBasePackageName();
     }
 
+    /** @hide */
+    @Override
+    public @Nullable String getFeatureId() {
+        return mFeatureId;
+    }
+
     @Override
     public ApplicationInfo getApplicationInfo() {
         if (mPackageInfo != null) {
@@ -2159,7 +2168,7 @@
         LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(),
                 flags | CONTEXT_REGISTER_PACKAGE);
         if (pi != null) {
-            ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken,
+            ContextImpl c = new ContextImpl(this, mMainThread, pi, null, null, mActivityToken,
                     new UserHandle(UserHandle.getUserId(application.uid)), flags, null, null);
 
             final int displayId = getDisplayId();
@@ -2187,15 +2196,15 @@
         if (packageName.equals("system") || packageName.equals("android")) {
             // The system resources are loaded in every application, so we can safely copy
             // the context without reloading Resources.
-            return new ContextImpl(this, mMainThread, mPackageInfo, null, mActivityToken, user,
-                    flags, null, null);
+            return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, null,
+                    mActivityToken, user, flags, null, null);
         }
 
         LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
                 flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
         if (pi != null) {
-            ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, user,
-                    flags, null, null);
+            ContextImpl c = new ContextImpl(this, mMainThread, pi, mFeatureId, null,
+                    mActivityToken, user, flags, null, null);
 
             final int displayId = getDisplayId();
 
@@ -2212,9 +2221,9 @@
     }
 
     @Override
-    public Context createContextAsUser(UserHandle user) {
+    public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) {
         try {
-            return createPackageContextAsUser(getPackageName(), mFlags, user);
+            return createPackageContextAsUser(getPackageName(), flags, user);
         } catch (NameNotFoundException e) {
             throw new IllegalStateException("Own package not found: package=" + getPackageName());
         }
@@ -2230,8 +2239,8 @@
         final ClassLoader classLoader = mPackageInfo.getSplitClassLoader(splitName);
         final String[] paths = mPackageInfo.getSplitPaths(splitName);
 
-        final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, splitName,
-                mActivityToken, mUser, mFlags, classLoader, null);
+        final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo,
+                mFeatureId, splitName, mActivityToken, mUser, mFlags, classLoader, null);
 
         final int displayId = getDisplayId();
 
@@ -2254,8 +2263,8 @@
             throw new IllegalArgumentException("overrideConfiguration must not be null");
         }
 
-        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName,
-                mActivityToken, mUser, mFlags, mClassLoader, null);
+        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId,
+                mSplitName, mActivityToken, mUser, mFlags, mClassLoader, null);
 
         final int displayId = getDisplayId();
         context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
@@ -2269,8 +2278,8 @@
             throw new IllegalArgumentException("display must not be null");
         }
 
-        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName,
-                mActivityToken, mUser, mFlags, mClassLoader, null);
+        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId,
+                mSplitName, mActivityToken, mUser, mFlags, mClassLoader, null);
 
         final int displayId = display.getDisplayId();
         context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
@@ -2280,19 +2289,25 @@
     }
 
     @Override
+    public @NonNull Context createFeatureContext(@Nullable String featureId) {
+        return new ContextImpl(this, mMainThread, mPackageInfo, featureId, mSplitName,
+                mActivityToken, mUser, mFlags, mClassLoader, null);
+    }
+
+    @Override
     public Context createDeviceProtectedStorageContext() {
         final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE)
                 | Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
-        return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser,
-                flags, mClassLoader, null);
+        return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName,
+                mActivityToken, mUser, flags, mClassLoader, null);
     }
 
     @Override
     public Context createCredentialProtectedStorageContext() {
         final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE)
                 | Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
-        return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser,
-                flags, mClassLoader, null);
+        return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName,
+                mActivityToken, mUser, flags, mClassLoader, null);
     }
 
     @Override
@@ -2436,8 +2451,8 @@
     @UnsupportedAppUsage
     static ContextImpl createSystemContext(ActivityThread mainThread) {
         LoadedApk packageInfo = new LoadedApk(mainThread);
-        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
-                null, null);
+        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,
+                0, null, null);
         context.setResources(packageInfo.getResources());
         context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                 context.mResourcesManager.getDisplayMetrics());
@@ -2454,7 +2469,7 @@
     static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
         final LoadedApk packageInfo = systemContext.mPackageInfo;
         ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo, null,
-                null, null, 0, null, null);
+                null, null, null, 0, null, null);
         context.setResources(createResources(null, packageInfo, null, displayId, null,
                 packageInfo.getCompatibilityInfo()));
         context.updateDisplay(displayId);
@@ -2477,8 +2492,8 @@
     static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
             String opPackageName) {
         if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
-        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
-                null, opPackageName);
+        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,
+                0, null, opPackageName);
         context.setResources(packageInfo.getResources());
         return context;
     }
@@ -2505,8 +2520,8 @@
             }
         }
 
-        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
-                activityToken, null, 0, classLoader, null);
+        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null,
+                activityInfo.splitName, activityToken, null, 0, classLoader, null);
 
         // Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY.
         displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY;
@@ -2534,9 +2549,9 @@
     }
 
     private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread,
-            @NonNull LoadedApk packageInfo, @Nullable String splitName,
-            @Nullable IBinder activityToken, @Nullable UserHandle user, int flags,
-            @Nullable ClassLoader classLoader, @Nullable String overrideOpPackageName) {
+            @NonNull LoadedApk packageInfo, @Nullable String featureId,
+            @Nullable String splitName, @Nullable IBinder activityToken, @Nullable UserHandle user,
+            int flags, @Nullable ClassLoader classLoader, @Nullable String overrideOpPackageName) {
         mOuterContext = this;
 
         // If creator didn't specify which storage to use, use the default
@@ -2587,7 +2602,7 @@
         }
 
         mOpPackageName = overrideOpPackageName != null ? overrideOpPackageName : opPackageName;
-
+        mFeatureId = featureId;
         mContentResolver = new ApplicationContentResolver(this, mainThread);
     }
 
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index dca00a2..31a29d4 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -351,10 +351,6 @@
     // Request a heap dump for the system server.
     void requestSystemServerHeapDump();
 
-    // Deprecated - This method is only used by a few internal components and it will soon start
-    // using bug report API (which will be restricted to a few, pre-defined apps).
-    // No new code should be calling it.
-    @UnsupportedAppUsage
     void requestBugReport(int bugreportType);
     void requestBugReportWithDescription(in @nullable String shareTitle,
                 in @nullable String shareDescription, int bugreportType);
@@ -364,7 +360,7 @@
      *  that are passed to this API as parameters
      *
      *  @param shareTitle should be a valid legible string less than 50 chars long
-     *  @param shareDescription should be less than 91 bytes when encoded into UTF-8 format
+     *  @param shareDescription should be less than 150 chars long
      *
      *  @throws IllegalArgumentException if shareTitle or shareDescription is too big or if the
      *          paremeters cannot be encoding to an UTF-8 charset.
@@ -372,13 +368,12 @@
     void requestTelephonyBugReport(in String shareTitle, in String shareDescription);
 
     /**
-     *  Deprecated - This method is only used by Wifi, and it will soon start using
-     *  bug report API.
+     *  This method is only used by Wifi.
      *
      *  Takes a minimal bugreport of Wifi-related state.
      *
      *  @param shareTitle should be a valid legible string less than 50 chars long
-     *  @param shareDescription should be less than 91 bytes when encoded into UTF-8 format
+     *  @param shareDescription should be less than 150 chars long
      *
      *  @throws IllegalArgumentException if shareTitle or shareDescription is too big or if the
      *          parameters cannot be encoding to an UTF-8 charset.
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 0ba1989..06288c0 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -158,7 +158,7 @@
      * @param activityToken Token of the size compatibility mode activity. It will be null when
      *                      switching to a activity that is not in size compatibility mode or the
      *                      configuration of the activity.
-     * @see com.android.server.wm.AppWindowToken#inSizeCompatMode
+     * @see com.android.server.wm.ActivityRecord#inSizeCompatMode
      */
     void onSizeCompatModeActivityChanged(int displayId, in IBinder activityToken);
 
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 316cab8..6dca5d9 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -997,8 +997,13 @@
     }
 
     /**
-     * @hide
+     * <p>
+     *  Gets the currently applied notification policy. If {@link #getCurrentInterruptionFilter}
+     * is equal to {@link #INTERRUPTION_FILTER_ALL}, then the consolidated notification policy
+     * will match the default notification policy returned by {@link #getNotificationPolicy}.
+     * </p>
      */
+    @Nullable
     public NotificationManager.Policy getConsolidatedNotificationPolicy() {
         INotificationManager service = getService();
         try {
@@ -1024,7 +1029,7 @@
      * Returns AutomaticZenRules owned by the caller.
      *
      * <p>
-     * Throws a SecurityException if policy access is granted to this package.
+     * Throws a SecurityException if policy access is not granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      */
     public Map<String, AutomaticZenRule> getAutomaticZenRules() {
@@ -1048,7 +1053,7 @@
      * Returns the AutomaticZenRule with the given id, if it exists and the caller has access.
      *
      * <p>
-     * Throws a SecurityException if policy access is granted to this package.
+     * Throws a SecurityException if policy access is not granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      *
      * <p>
@@ -1068,7 +1073,7 @@
      * Creates the given zen rule.
      *
      * <p>
-     * Throws a SecurityException if policy access is granted to this package.
+     * Throws a SecurityException if policy access is not granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      *
      * @param automaticZenRule the rule to create.
@@ -1087,7 +1092,7 @@
      * Updates the given zen rule.
      *
      * <p>
-     * Throws a SecurityException if policy access is granted to this package.
+     * Throws a SecurityException if policy access is not granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      *
      * <p>
@@ -1129,7 +1134,7 @@
      * Deletes the automatic zen rule with the given id.
      *
      * <p>
-     * Throws a SecurityException if policy access is granted to this package.
+     * Throws a SecurityException if policy access is not granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      *
      * <p>
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 9e6054c..68ab89c 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -884,21 +884,24 @@
      * @param activityToken optional token to clean up Activity resources
      */
     private void cleanupReferences(IBinder activityToken) {
-        if (activityToken != null) {
-            ActivityResources activityResources = mActivityResourceReferences.get(activityToken);
-            if (activityResources != null) {
-                ArrayUtils.unstableRemoveIf(activityResources.activityResources,
-                        sEmptyReferencePredicate);
+        synchronized (this) {
+            if (activityToken != null) {
+                ActivityResources activityResources = mActivityResourceReferences.get(
+                        activityToken);
+                if (activityResources != null) {
+                    ArrayUtils.unstableRemoveIf(activityResources.activityResources,
+                            sEmptyReferencePredicate);
+                }
+            } else {
+                ArrayUtils.unstableRemoveIf(mResourceReferences, sEmptyReferencePredicate);
             }
-        } else {
-            ArrayUtils.unstableRemoveIf(mResourceReferences, sEmptyReferencePredicate);
-        }
 
-        for (int index = mResourcesWithLoaders.size() - 1; index >= 0; index--) {
-            ResourcesWithLoaders resourcesWithLoaders = mResourcesWithLoaders.get(index);
-            Resources resources = resourcesWithLoaders.resources();
-            if (resources == null) {
-                mResourcesWithLoaders.remove(index);
+            for (int index = mResourcesWithLoaders.size() - 1; index >= 0; index--) {
+                ResourcesWithLoaders resourcesWithLoaders = mResourcesWithLoaders.get(index);
+                Resources resources = resourcesWithLoaders.resources();
+                if (resources == null) {
+                    mResourcesWithLoaders.remove(index);
+                }
             }
         }
     }
diff --git a/core/java/android/app/SyncNotedAppOp.java b/core/java/android/app/SyncNotedAppOp.java
index f7b83d4..065d5de 100644
--- a/core/java/android/app/SyncNotedAppOp.java
+++ b/core/java/android/app/SyncNotedAppOp.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 
 import com.android.internal.annotations.Immutable;
 
@@ -33,6 +34,7 @@
 @Immutable
 public final class SyncNotedAppOp {
     private final int mOpCode;
+    private final @Nullable String mFeatureId;
 
     /**
      * @return The op that was noted.
@@ -42,14 +44,23 @@
     }
 
     /**
+     * @return The {@link android.content.Context#createFeatureContext Feature} in the app
+     */
+    public @Nullable String getFeatureId() {
+        return mFeatureId;
+    }
+
+    /**
      * Create a new sync op description
      *
      * @param opCode The op that was noted
      *
      * @hide
      */
-    public SyncNotedAppOp(@IntRange(from = 0, to = AppOpsManager._NUM_OP - 1) int opCode) {
+    public SyncNotedAppOp(@IntRange(from = 0, to = AppOpsManager._NUM_OP - 1) int opCode,
+            @Nullable String featureId) {
         mOpCode = opCode;
+        mFeatureId = featureId;
     }
 
     @Override
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index e81dc1c..8350fa1 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -152,7 +152,7 @@
 import android.os.image.DynamicSystemManager;
 import android.os.image.IDynamicSystemService;
 import android.os.storage.StorageManager;
-import android.os.telephony.TelephonyRegistryManager;
+import android.telephony.TelephonyRegistryManager;
 import android.permission.PermissionControllerManager;
 import android.permission.PermissionManager;
 import android.print.IPrintManager;
@@ -611,7 +611,7 @@
             new CachedServiceFetcher<TelephonyRegistryManager>() {
                 @Override
                 public TelephonyRegistryManager createService(ContextImpl ctx) {
-                    return new TelephonyRegistryManager();
+                    return new TelephonyRegistryManager(ctx);
                 }});
 
         registerService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class,
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index c3c383c..375a06e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2330,6 +2330,12 @@
             "android.app.action.ADMIN_POLICY_COMPLIANCE";
 
     /**
+     * Maximum supported password length. Kind-of arbitrary.
+     * @hide
+     */
+    public static final int MAX_PASSWORD_LENGTH = 16;
+
+    /**
      * Return true if the given administrator component is currently active (enabled) in the system.
      *
      * @param admin The administrator component to check for.
@@ -3233,6 +3239,22 @@
     }
 
     /**
+     * Returns minimum PasswordMetrics that satisfies all admin policies.
+     *
+     * @hide
+     */
+    public PasswordMetrics getPasswordMinimumMetrics(@UserIdInt int userHandle) {
+        if (mService != null) {
+            try {
+                return mService.getPasswordMinimumMetrics(userHandle);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return null;
+    }
+
+    /**
      * Called by an application that is administering the device to set the length of the password
      * history. After setting this, the user will not be able to enter a new password that is the
      * same as any password in the history. Note that the current password will remain until the
@@ -3415,8 +3437,7 @@
         if (!pm.hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN)) {
             return 0;
         }
-        // Kind-of arbitrary.
-        return 16;
+        return MAX_PASSWORD_LENGTH;
     }
 
     /**
@@ -6612,6 +6633,8 @@
      * The calling device admin must be a profile owner or device owner. If it is not, a security
      * exception will be thrown.
      *
+     * <p>NOTE: Performs disk I/O and shouldn't be called on the main thread.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param filter The IntentFilter for which a default handler is added.
      * @param activity The Activity that is added as default intent handler.
@@ -7182,7 +7205,8 @@
      * used, calling with an empty list only allows the built-in system services. Any non-system
      * accessibility service that's currently enabled must be included in the list.
      * <p>
-     * System accessibility services are always available to the user the list can't modify this.
+     * System accessibility services are always available to the user and this method can't
+     * disable them.
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageNames List of accessibility service package names.
      * @return {@code true} if the operation succeeded, or {@code false} if the list didn't
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 0da5b7a..7d2c54e 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -72,6 +72,8 @@
     void setPasswordMinimumNonLetter(in ComponentName who, int length, boolean parent);
     int getPasswordMinimumNonLetter(in ComponentName who, int userHandle, boolean parent);
 
+    PasswordMetrics getPasswordMinimumMetrics(int userHandle);
+
     void setPasswordHistoryLength(in ComponentName who, int length, boolean parent);
     int getPasswordHistoryLength(in ComponentName who, int userHandle, boolean parent);
 
diff --git a/core/java/android/app/admin/PasswordMetrics.java b/core/java/android/app/admin/PasswordMetrics.java
index 9929855..d9bfde5 100644
--- a/core/java/android/app/admin/PasswordMetrics.java
+++ b/core/java/android/app/admin/PasswordMetrics.java
@@ -16,45 +16,65 @@
 
 package android.app.admin;
 
+import static android.app.admin.DevicePolicyManager.MAX_PASSWORD_LENGTH;
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
 
+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_PATTERN;
+import static com.android.internal.widget.LockPatternUtils.MIN_LOCK_PASSWORD_SIZE;
+import static com.android.internal.widget.PasswordValidationError.CONTAINS_INVALID_CHARACTERS;
+import static com.android.internal.widget.PasswordValidationError.CONTAINS_SEQUENCE;
+import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_DIGITS;
+import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_LETTERS;
+import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_LOWER_CASE;
+import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_NON_DIGITS;
+import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_NON_LETTER;
+import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_SYMBOLS;
+import static com.android.internal.widget.PasswordValidationError.NOT_ENOUGH_UPPER_CASE;
+import static com.android.internal.widget.PasswordValidationError.TOO_LONG;
+import static com.android.internal.widget.PasswordValidationError.TOO_SHORT;
+import static com.android.internal.widget.PasswordValidationError.WEAK_CREDENTIAL_TYPE;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.app.admin.DevicePolicyManager.PasswordComplexity;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.Log;
 
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
 import com.android.internal.widget.LockPatternUtils.CredentialType;
+import com.android.internal.widget.LockscreenCredential;
+import com.android.internal.widget.PasswordValidationError;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
 
 /**
  * A class that represents the metrics of a credential that are used to decide whether or not a
- * credential meets the requirements. If the credential is a pattern, only quality matters.
+ * credential meets the requirements.
  *
  * {@hide}
  */
-public class PasswordMetrics implements Parcelable {
+public final class PasswordMetrics implements Parcelable {
+    private static final String TAG = "PasswordMetrics";
+
     // Maximum allowed number of repeated or ordered characters in a sequence before we'll
     // consider it a complex PIN/password.
     public static final int MAX_ALLOWED_SEQUENCE = 3;
 
-    public int quality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+    public @CredentialType int credType;
+    // Fields below only make sense when credType is PASSWORD.
     public int length = 0;
     public int letters = 0;
     public int upperCase = 0;
@@ -62,139 +82,62 @@
     public int numeric = 0;
     public int symbols = 0;
     public int nonLetter = 0;
+    public int nonNumeric = 0;
+    // MAX_VALUE is the most relaxed value, any sequence is ok, e.g. 123456789. 4 would forbid it.
+    public int seqLength = Integer.MAX_VALUE;
 
-    public PasswordMetrics() {}
-
-    public PasswordMetrics(int quality) {
-        this.quality = quality;
+    public PasswordMetrics(int credType) {
+        this.credType = credType;
     }
 
-    public PasswordMetrics(int quality, int length) {
-        this.quality = quality;
+    public PasswordMetrics(int credType , int length, int letters, int upperCase, int lowerCase,
+            int numeric, int symbols, int nonLetter, int nonNumeric, int seqLength) {
+        this.credType = credType;
         this.length = length;
-    }
-
-    public PasswordMetrics(int quality, int length, int letters, int upperCase, int lowerCase,
-            int numeric, int symbols, int nonLetter) {
-        this(quality, length);
         this.letters = letters;
         this.upperCase = upperCase;
         this.lowerCase = lowerCase;
         this.numeric = numeric;
         this.symbols = symbols;
         this.nonLetter = nonLetter;
+        this.nonNumeric = nonNumeric;
+        this.seqLength = seqLength;
     }
 
-    private PasswordMetrics(Parcel in) {
-        quality = in.readInt();
-        length = in.readInt();
-        letters = in.readInt();
-        upperCase = in.readInt();
-        lowerCase = in.readInt();
-        numeric = in.readInt();
-        symbols = in.readInt();
-        nonLetter = in.readInt();
-    }
-
-    /** Returns the min quality allowed by {@code complexityLevel}. */
-    public static int complexityLevelToMinQuality(@PasswordComplexity int complexityLevel) {
-        // this would be the quality of the first metrics since mMetrics is sorted in ascending
-        // order of quality
-        return PasswordComplexityBucket
-                .complexityLevelToBucket(complexityLevel).mMetrics[0].quality;
-    }
-
-    /**
-     * Returns a merged minimum {@link PasswordMetrics} requirements that a new password must meet
-     * to fulfil {@code requestedQuality}, {@code requiresNumeric} and {@code
-     * requiresLettersOrSymbols}, which are derived from {@link DevicePolicyManager} requirements,
-     * and {@code complexityLevel}.
-     *
-     * <p>Note that we are taking {@code userEnteredPasswordQuality} into account because there are
-     * more than one set of metrics to meet the minimum complexity requirement and inspecting what
-     * the user has entered can help determine whether the alphabetic or alphanumeric set of metrics
-     * should be used. For example, suppose minimum complexity requires either ALPHABETIC(8+), or
-     * ALPHANUMERIC(6+). If the user has entered "a", the length requirement displayed on the UI
-     * would be 8. Then the user appends "1" to make it "a1". We now know the user is entering
-     * an alphanumeric password so we would update the min complexity required min length to 6.
-     */
-    public static PasswordMetrics getMinimumMetrics(@PasswordComplexity int complexityLevel,
-            int userEnteredPasswordQuality, int requestedQuality, boolean requiresNumeric,
-            boolean requiresLettersOrSymbols) {
-        int targetQuality = Math.max(
-                userEnteredPasswordQuality,
-                getActualRequiredQuality(
-                        requestedQuality, requiresNumeric, requiresLettersOrSymbols));
-        return getTargetQualityMetrics(complexityLevel, targetQuality);
-    }
-
-    /**
-     * Returns the {@link PasswordMetrics} at {@code complexityLevel} which the metrics quality
-     * is the same as {@code targetQuality}.
-     *
-     * <p>If {@code complexityLevel} does not allow {@code targetQuality}, returns the metrics
-     * with the min quality at {@code complexityLevel}.
-     */
-    // TODO(bernardchau): update tests to test getMinimumMetrics and change this to be private
-    @VisibleForTesting
-    public static PasswordMetrics getTargetQualityMetrics(
-            @PasswordComplexity int complexityLevel, int targetQuality) {
-        PasswordComplexityBucket targetBucket =
-                PasswordComplexityBucket.complexityLevelToBucket(complexityLevel);
-        for (PasswordMetrics metrics : targetBucket.mMetrics) {
-            if (targetQuality == metrics.quality) {
-                return metrics;
-            }
-        }
-        // none of the metrics at complexityLevel has targetQuality, return metrics with min quality
-        // see test case testGetMinimumMetrics_actualRequiredQualityStricter for an example, where
-        // min complexity allows at least NUMERIC_COMPLEX, user has not entered anything yet, and
-        // requested quality is NUMERIC
-        return targetBucket.mMetrics[0];
-    }
-
-    /**
-     * Finds out the actual quality requirement based on whether quality is {@link
-     * DevicePolicyManager#PASSWORD_QUALITY_COMPLEX} and whether digits, letters or symbols are
-     * required.
-     */
-    @VisibleForTesting
-    // TODO(bernardchau): update tests to test getMinimumMetrics and change this to be private
-    public static int getActualRequiredQuality(
-            int requestedQuality, boolean requiresNumeric, boolean requiresLettersOrSymbols) {
-        if (requestedQuality != PASSWORD_QUALITY_COMPLEX) {
-            return requestedQuality;
-        }
-
-        // find out actual password quality from complex requirements
-        if (requiresNumeric && requiresLettersOrSymbols) {
-            return PASSWORD_QUALITY_ALPHANUMERIC;
-        }
-        if (requiresLettersOrSymbols) {
-            return PASSWORD_QUALITY_ALPHABETIC;
-        }
-        if (requiresNumeric) {
-            // cannot specify numeric complex using complex quality so this must be numeric
-            return PASSWORD_QUALITY_NUMERIC;
-        }
-
-        // reaching here means dpm sets quality to complex without specifying any requirements
-        return PASSWORD_QUALITY_UNSPECIFIED;
+    private PasswordMetrics(PasswordMetrics other) {
+        this(other.credType, other.length, other.letters, other.upperCase, other.lowerCase,
+                other.numeric, other.symbols, other.nonLetter, other.nonNumeric, other.seqLength);
     }
 
     /**
      * Returns {@code complexityLevel} or {@link DevicePolicyManager#PASSWORD_COMPLEXITY_NONE}
      * if {@code complexityLevel} is not valid.
+     *
+     * TODO: move to PasswordPolicy
      */
     @PasswordComplexity
     public static int sanitizeComplexityLevel(@PasswordComplexity int complexityLevel) {
-        return PasswordComplexityBucket.complexityLevelToBucket(complexityLevel).mComplexityLevel;
+        switch (complexityLevel) {
+            case PASSWORD_COMPLEXITY_HIGH:
+            case PASSWORD_COMPLEXITY_MEDIUM:
+            case PASSWORD_COMPLEXITY_LOW:
+            case PASSWORD_COMPLEXITY_NONE:
+                return complexityLevel;
+            default:
+                Log.w(TAG, "Invalid password complexity used: " + complexityLevel);
+                return PASSWORD_COMPLEXITY_NONE;
+        }
     }
 
-    public boolean isDefault() {
-        return quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
-                && length == 0 && letters == 0 && upperCase == 0 && lowerCase == 0
-                && numeric == 0 && symbols == 0 && nonLetter == 0;
+    private static boolean hasInvalidCharacters(byte[] password) {
+        // Allow non-control Latin-1 characters only.
+        for (byte b : password) {
+            char c = (char) b;
+            if (c < 32 || c > 127) {
+                return true;
+            }
+        }
+        return false;
     }
 
     @Override
@@ -204,7 +147,7 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(quality);
+        dest.writeInt(credType);
         dest.writeInt(length);
         dest.writeInt(letters);
         dest.writeInt(upperCase);
@@ -212,12 +155,25 @@
         dest.writeInt(numeric);
         dest.writeInt(symbols);
         dest.writeInt(nonLetter);
+        dest.writeInt(nonNumeric);
+        dest.writeInt(seqLength);
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<PasswordMetrics> CREATOR
+    public static final @NonNull Parcelable.Creator<PasswordMetrics> CREATOR
             = new Parcelable.Creator<PasswordMetrics>() {
         public PasswordMetrics createFromParcel(Parcel in) {
-            return new PasswordMetrics(in);
+            int credType = in.readInt();
+            int length = in.readInt();
+            int letters = in.readInt();
+            int upperCase = in.readInt();
+            int lowerCase = in.readInt();
+            int numeric = in.readInt();
+            int symbols = in.readInt();
+            int nonLetter = in.readInt();
+            int nonNumeric = in.readInt();
+            int seqLength = in.readInt();
+            return new PasswordMetrics(credType, length, letters, upperCase, lowerCase, numeric,
+                    symbols, nonLetter, nonNumeric, seqLength);
         }
 
         public PasswordMetrics[] newArray(int size) {
@@ -226,21 +182,21 @@
     };
 
     /**
-     * Returnsthe {@code PasswordMetrics} for a given credential.
+     * Returns the {@code PasswordMetrics} for a given credential.
      *
      * If the credential is a pin or a password, equivalent to {@link #computeForPassword(byte[])}.
      * {@code credential} cannot be null when {@code type} is
      * {@link com.android.internal.widget.LockPatternUtils#CREDENTIAL_TYPE_PASSWORD}.
      */
-    public static PasswordMetrics computeForCredential(
-            @CredentialType int type, byte[] credential) {
-        if (type == CREDENTIAL_TYPE_PASSWORD) {
-            Preconditions.checkNotNull(credential, "credential cannot be null");
-            return PasswordMetrics.computeForPassword(credential);
-        } else if (type == CREDENTIAL_TYPE_PATTERN)  {
-            return new PasswordMetrics(PASSWORD_QUALITY_SOMETHING);
-        } else /* if (type == CREDENTIAL_TYPE_NONE) */ {
-            return new PasswordMetrics(PASSWORD_QUALITY_UNSPECIFIED);
+    public static PasswordMetrics computeForCredential(LockscreenCredential credential) {
+        if (credential.isPassword()) {
+            return PasswordMetrics.computeForPassword(credential.getCredential());
+        } else if (credential.isPattern())  {
+            return new PasswordMetrics(CREDENTIAL_TYPE_PATTERN);
+        } else if (credential.isNone()) {
+            return new PasswordMetrics(CREDENTIAL_TYPE_NONE);
+        } else {
+            throw new IllegalArgumentException("Unknown credential type " + credential.getType());
         }
     }
 
@@ -255,16 +211,19 @@
         int numeric = 0;
         int symbols = 0;
         int nonLetter = 0;
+        int nonNumeric = 0;
         final int length = password.length;
         for (byte b : password) {
             switch (categoryChar((char) b)) {
                 case CHAR_LOWER_CASE:
                     letters++;
                     lowerCase++;
+                    nonNumeric++;
                     break;
                 case CHAR_UPPER_CASE:
                     letters++;
                     upperCase++;
+                    nonNumeric++;
                     break;
                 case CHAR_DIGIT:
                     numeric++;
@@ -273,53 +232,14 @@
                 case CHAR_SYMBOL:
                     symbols++;
                     nonLetter++;
+                    nonNumeric++;
                     break;
             }
         }
 
-        // Determine the quality of the password
-        final boolean hasNumeric = numeric > 0;
-        final boolean hasNonNumeric = (letters + symbols) > 0;
-        final int quality;
-        if (hasNonNumeric && hasNumeric) {
-            quality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
-        } else if (hasNonNumeric) {
-            quality = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
-        } else if (hasNumeric) {
-            quality = maxLengthSequence(password) > MAX_ALLOWED_SEQUENCE
-                    ? DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
-                    : DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
-        } else {
-            quality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
-        }
-
-        return new PasswordMetrics(
-                quality, length, letters, upperCase, lowerCase, numeric, symbols, nonLetter);
-    }
-
-    @Override
-    public boolean equals(Object other) {
-        if (!(other instanceof PasswordMetrics)) {
-            return false;
-        }
-        PasswordMetrics o = (PasswordMetrics) other;
-        return this.quality == o.quality
-                && this.length == o.length
-                && this.letters == o.letters
-                && this.upperCase == o.upperCase
-                && this.lowerCase == o.lowerCase
-                && this.numeric == o.numeric
-                && this.symbols == o.symbols
-                && this.nonLetter == o.nonLetter;
-    }
-
-    private boolean satisfiesBucket(PasswordMetrics... bucket) {
-        for (PasswordMetrics metrics : bucket) {
-            if (this.quality == metrics.quality) {
-                return this.length >= metrics.length;
-            }
-        }
-        return false;
+        final int seqLength = maxLengthSequence(password);
+        return new PasswordMetrics(CREDENTIAL_TYPE_PASSWORD, length, letters, upperCase, lowerCase,
+                numeric, symbols, nonLetter, nonNumeric, seqLength);
     }
 
     /**
@@ -404,108 +324,394 @@
         }
     }
 
-    /** Determines the {@link PasswordComplexity} of this {@link PasswordMetrics}. */
-    @PasswordComplexity
-    public int determineComplexity() {
-        for (PasswordComplexityBucket bucket : PasswordComplexityBucket.BUCKETS) {
-            if (satisfiesBucket(bucket.mMetrics)) {
-                return bucket.mComplexityLevel;
-            }
+    /**
+     * Returns the weakest metrics that is stricter or equal to all given metrics.
+     *
+     * TODO: move to PasswordPolicy
+     */
+    public static PasswordMetrics merge(List<PasswordMetrics> metrics) {
+        PasswordMetrics result = new PasswordMetrics(CREDENTIAL_TYPE_NONE);
+        for (PasswordMetrics m : metrics) {
+            result.maxWith(m);
         }
-        return PASSWORD_COMPLEXITY_NONE;
+
+        return result;
     }
 
     /**
-     * Requirements in terms of {@link PasswordMetrics} for each {@link PasswordComplexity}.
+     * Makes current metric at least as strong as {@code other} in every criterion.
+     *
+     * TODO: move to PasswordPolicy
      */
-    private static class PasswordComplexityBucket {
-        /**
-         * Definition of {@link DevicePolicyManager#PASSWORD_COMPLEXITY_HIGH} in terms of
-         * {@link PasswordMetrics}.
-         */
-        private static final PasswordComplexityBucket HIGH =
-                new PasswordComplexityBucket(
-                        PASSWORD_COMPLEXITY_HIGH,
-                        new PasswordMetrics(
-                                DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX, /* length= */
-                                8),
-                        new PasswordMetrics(
-                                DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, /* length= */ 6),
-                        new PasswordMetrics(
-                                DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, /* length= */
-                                6));
+    private void maxWith(PasswordMetrics other) {
+        credType = Math.max(credType, other.credType);
+        if (credType != CREDENTIAL_TYPE_PASSWORD) {
+            return;
+        }
+        length = Math.max(length, other.length);
+        letters = Math.max(letters, other.letters);
+        upperCase = Math.max(upperCase, other.upperCase);
+        lowerCase = Math.max(lowerCase, other.lowerCase);
+        numeric = Math.max(numeric, other.numeric);
+        symbols = Math.max(symbols, other.symbols);
+        nonLetter = Math.max(nonLetter, other.nonLetter);
+        nonNumeric = Math.max(nonNumeric, other.nonNumeric);
+        seqLength = Math.min(seqLength, other.seqLength);
+    }
 
-        /**
-         * Definition of {@link DevicePolicyManager#PASSWORD_COMPLEXITY_MEDIUM} in terms of
-         * {@link PasswordMetrics}.
-         */
-        private static final PasswordComplexityBucket MEDIUM =
-                new PasswordComplexityBucket(
-                        PASSWORD_COMPLEXITY_MEDIUM,
-                        new PasswordMetrics(
-                                DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX, /* length= */
-                                4),
-                        new PasswordMetrics(
-                                DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, /* length= */ 4),
-                        new PasswordMetrics(
-                                DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, /* length= */
-                                4));
+    /**
+     * Returns minimum password quality for a given complexity level.
+     *
+     * TODO: this function is used for determining allowed credential types, so it should return
+     * credential type rather than 'quality'.
+     *
+     * TODO: move to PasswordPolicy
+     */
+    public static int complexityLevelToMinQuality(int complexity) {
+        switch (complexity) {
+            case PASSWORD_COMPLEXITY_HIGH:
+            case PASSWORD_COMPLEXITY_MEDIUM:
+                return PASSWORD_QUALITY_NUMERIC_COMPLEX;
+            case PASSWORD_COMPLEXITY_LOW:
+                return PASSWORD_QUALITY_SOMETHING;
+            case PASSWORD_COMPLEXITY_NONE:
+            default:
+                return PASSWORD_QUALITY_UNSPECIFIED;
+        }
+    }
 
-        /**
-         * Definition of {@link DevicePolicyManager#PASSWORD_COMPLEXITY_LOW} in terms of
-         * {@link PasswordMetrics}.
-         */
-        private static final PasswordComplexityBucket LOW =
-                new PasswordComplexityBucket(
-                        PASSWORD_COMPLEXITY_LOW,
-                        new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING),
-                        new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC),
-                        new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX),
-                        new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC),
-                        new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC));
-
-        /**
-         * A special bucket to represent {@link DevicePolicyManager#PASSWORD_COMPLEXITY_NONE}.
-         */
-        private static final PasswordComplexityBucket NONE =
-                new PasswordComplexityBucket(PASSWORD_COMPLEXITY_NONE, new PasswordMetrics());
-
-        /** Array containing all buckets from high to low. */
-        private static final PasswordComplexityBucket[] BUCKETS =
-                new PasswordComplexityBucket[] {HIGH, MEDIUM, LOW};
-
-        @PasswordComplexity
-        private final int mComplexityLevel;
-        private final PasswordMetrics[] mMetrics;
-
-        /**
-         * @param metricsArray must be sorted in ascending order of {@link #quality}.
-         */
-        private PasswordComplexityBucket(@PasswordComplexity int complexityLevel,
-                PasswordMetrics... metricsArray) {
-            int previousQuality = PASSWORD_QUALITY_UNSPECIFIED;
-            for (PasswordMetrics metrics : metricsArray) {
-                if (metrics.quality < previousQuality) {
-                    throw new IllegalArgumentException("metricsArray must be sorted in ascending"
-                            + " order of quality");
-                }
-                previousQuality = metrics.quality;
+    /**
+     * Enum representing requirements for each complexity level.
+     *
+     * TODO: move to PasswordPolicy
+     */
+    private enum ComplexityBucket {
+        // Keep ordered high -> low.
+        BUCKET_HIGH(PASSWORD_COMPLEXITY_HIGH) {
+            @Override
+            boolean canHaveSequence() {
+                return false;
             }
 
-            this.mMetrics = metricsArray;
-            this.mComplexityLevel = complexityLevel;
+            @Override
+            int getMinimumLength(boolean containsNonNumeric) {
+                return containsNonNumeric ? 6 : 8;
+            }
 
+            @Override
+            boolean allowsNumericPassword() {
+                return false;
+            }
+
+            @Override
+            boolean allowsCredType(int credType) {
+                return credType == CREDENTIAL_TYPE_PASSWORD;
+            }
+        },
+        BUCKET_MEDIUM(PASSWORD_COMPLEXITY_MEDIUM) {
+            @Override
+            boolean canHaveSequence() {
+                return false;
+            }
+
+            @Override
+            int getMinimumLength(boolean containsNonNumeric) {
+                return 4;
+            }
+
+            @Override
+            boolean allowsNumericPassword() {
+                return false;
+            }
+
+            @Override
+            boolean allowsCredType(int credType) {
+                return credType == CREDENTIAL_TYPE_PASSWORD;
+            }
+        },
+        BUCKET_LOW(PASSWORD_COMPLEXITY_LOW) {
+            @Override
+            boolean canHaveSequence() {
+                return true;
+            }
+
+            @Override
+            int getMinimumLength(boolean containsNonNumeric) {
+                return 0;
+            }
+
+            @Override
+            boolean allowsNumericPassword() {
+                return true;
+            }
+
+            @Override
+            boolean allowsCredType(int credType) {
+                return credType != CREDENTIAL_TYPE_NONE;
+            }
+        },
+        BUCKET_NONE(PASSWORD_COMPLEXITY_NONE) {
+            @Override
+            boolean canHaveSequence() {
+                return true;
+            }
+
+            @Override
+            int getMinimumLength(boolean containsNonNumeric) {
+                return 0;
+            }
+
+            @Override
+            boolean allowsNumericPassword() {
+                return true;
+            }
+
+            @Override
+            boolean allowsCredType(int credType) {
+                return true;
+            }
+        };
+
+        int mComplexityLevel;
+
+        abstract boolean canHaveSequence();
+        abstract int getMinimumLength(boolean containsNonNumeric);
+        abstract boolean allowsNumericPassword();
+        abstract boolean allowsCredType(int credType);
+
+        ComplexityBucket(int complexityLevel) {
+            this.mComplexityLevel = complexityLevel;
         }
 
-        /** Returns the bucket that {@code complexityLevel} represents. */
-        private static PasswordComplexityBucket complexityLevelToBucket(
-                @PasswordComplexity int complexityLevel) {
-            for (PasswordComplexityBucket bucket : BUCKETS) {
+        static ComplexityBucket forComplexity(int complexityLevel) {
+            for (ComplexityBucket bucket : values()) {
                 if (bucket.mComplexityLevel == complexityLevel) {
                     return bucket;
                 }
             }
-            return NONE;
+            throw new IllegalArgumentException("Invalid complexity level: " + complexityLevel);
         }
     }
+
+    /**
+     * Returns whether current metrics satisfies a given complexity bucket.
+     *
+     * TODO: move inside ComplexityBucket.
+     */
+    private boolean satisfiesBucket(ComplexityBucket bucket) {
+        if (!bucket.allowsCredType(credType)) {
+            return false;
+        }
+        if (credType != CREDENTIAL_TYPE_PASSWORD) {
+            return true;
+        }
+        return (bucket.canHaveSequence() || seqLength <= MAX_ALLOWED_SEQUENCE)
+                && length >= bucket.getMinimumLength(nonNumeric > 0 /* hasNonNumeric */);
+    }
+
+    /**
+     * Returns the maximum complexity level satisfied by password with this metrics.
+     *
+     * TODO: move inside ComplexityBucket.
+     */
+    public int determineComplexity() {
+        for (ComplexityBucket bucket : ComplexityBucket.values()) {
+            if (satisfiesBucket(bucket)) {
+                return bucket.mComplexityLevel;
+            }
+        }
+        throw new IllegalStateException("Failed to figure out complexity for a given metrics");
+    }
+
+    /**
+     * Validates password against minimum metrics and complexity.
+     *
+     * @param adminMetrics - minimum metrics to satisfy admin requirements.
+     * @param minComplexity - minimum complexity imposed by the requester.
+     * @param isPin - whether it is PIN that should be only digits
+     * @param password - password to validate.
+     * @return a list of password validation errors. An empty list means the password is OK.
+     *
+     * TODO: move to PasswordPolicy
+     */
+    public static List<PasswordValidationError> validatePassword(
+            PasswordMetrics adminMetrics, int minComplexity, boolean isPin, byte[] password) {
+
+        if (hasInvalidCharacters(password)) {
+            return Collections.singletonList(
+                    new PasswordValidationError(CONTAINS_INVALID_CHARACTERS, 0));
+        }
+
+        final PasswordMetrics enteredMetrics = computeForPassword(password);
+        return validatePasswordMetrics(adminMetrics, minComplexity, isPin, enteredMetrics);
+    }
+
+    /**
+     * Validates password metrics against minimum metrics and complexity
+     *
+     * @param adminMetrics - minimum metrics to satisfy admin requirements.
+     * @param minComplexity - minimum complexity imposed by the requester.
+     * @param isPin - whether it is PIN that should be only digits
+     * @param actualMetrics - metrics for password to validate.
+     * @return a list of password validation errors. An empty list means the password is OK.
+     *
+     * TODO: move to PasswordPolicy
+     */
+    public static List<PasswordValidationError> validatePasswordMetrics(
+            PasswordMetrics adminMetrics, int minComplexity, boolean isPin,
+            PasswordMetrics actualMetrics) {
+        final ComplexityBucket bucket = ComplexityBucket.forComplexity(minComplexity);
+
+        // Make sure credential type is satisfactory.
+        // TODO: stop relying on credential type ordering.
+        if (actualMetrics.credType < adminMetrics.credType
+                || !bucket.allowsCredType(actualMetrics.credType)) {
+            return Collections.singletonList(new PasswordValidationError(WEAK_CREDENTIAL_TYPE, 0));
+        }
+        // TODO: this needs to be modified if CREDENTIAL_TYPE_PIN is added.
+        if (actualMetrics.credType != CREDENTIAL_TYPE_PASSWORD) {
+            return Collections.emptyList(); // Nothing to check for pattern or none.
+        }
+
+        if (isPin && actualMetrics.nonNumeric > 0) {
+            return Collections.singletonList(
+                    new PasswordValidationError(CONTAINS_INVALID_CHARACTERS, 0));
+        }
+
+        final ArrayList<PasswordValidationError> result = new ArrayList<>();
+        if (actualMetrics.length > MAX_PASSWORD_LENGTH) {
+            result.add(new PasswordValidationError(TOO_LONG, MAX_PASSWORD_LENGTH));
+        }
+
+        final PasswordMetrics minMetrics = applyComplexity(adminMetrics, isPin, bucket);
+
+        // Clamp required length between maximum and minimum valid values.
+        minMetrics.length = Math.min(MAX_PASSWORD_LENGTH,
+                Math.max(minMetrics.length, MIN_LOCK_PASSWORD_SIZE));
+        minMetrics.removeOverlapping();
+
+        comparePasswordMetrics(minMetrics, actualMetrics, result);
+
+        return result;
+    }
+
+    /**
+     * TODO: move to PasswordPolicy
+     */
+    private static void comparePasswordMetrics(PasswordMetrics minMetrics,
+            PasswordMetrics actualMetrics, ArrayList<PasswordValidationError> result) {
+        if (actualMetrics.length < minMetrics.length) {
+            result.add(new PasswordValidationError(TOO_SHORT, minMetrics.length));
+        }
+        if (actualMetrics.letters < minMetrics.letters) {
+            result.add(new PasswordValidationError(NOT_ENOUGH_LETTERS, minMetrics.letters));
+        }
+        if (actualMetrics.upperCase < minMetrics.upperCase) {
+            result.add(new PasswordValidationError(NOT_ENOUGH_UPPER_CASE, minMetrics.upperCase));
+        }
+        if (actualMetrics.lowerCase < minMetrics.lowerCase) {
+            result.add(new PasswordValidationError(NOT_ENOUGH_LOWER_CASE, minMetrics.lowerCase));
+        }
+        if (actualMetrics.numeric < minMetrics.numeric) {
+            result.add(new PasswordValidationError(NOT_ENOUGH_DIGITS, minMetrics.numeric));
+        }
+        if (actualMetrics.symbols < minMetrics.symbols) {
+            result.add(new PasswordValidationError(NOT_ENOUGH_SYMBOLS, minMetrics.symbols));
+        }
+        if (actualMetrics.nonLetter < minMetrics.nonLetter) {
+            result.add(new PasswordValidationError(NOT_ENOUGH_NON_LETTER, minMetrics.nonLetter));
+        }
+        if (actualMetrics.nonNumeric < minMetrics.nonNumeric) {
+            result.add(new PasswordValidationError(NOT_ENOUGH_NON_DIGITS, minMetrics.nonNumeric));
+        }
+        if (actualMetrics.seqLength > minMetrics.seqLength) {
+            result.add(new PasswordValidationError(CONTAINS_SEQUENCE, 0));
+        }
+    }
+
+    /**
+     * Drop requirements that are superseded by others, e.g. if it is required to have 5 upper case
+     * letters and 5 lower case letters, there is no need to require minimum number of letters to
+     * be 10 since it will be fulfilled once upper and lower case requirements are fulfilled.
+     *
+     * TODO: move to PasswordPolicy
+     */
+    private void removeOverlapping() {
+        // upperCase + lowerCase can override letters
+        final int indirectLetters = upperCase + lowerCase;
+
+        // numeric + symbols can override nonLetter
+        final int indirectNonLetter = numeric + symbols;
+
+        // letters + symbols can override nonNumeric
+        final int effectiveLetters = Math.max(letters, indirectLetters);
+        final int indirectNonNumeric = effectiveLetters + symbols;
+
+        // letters + nonLetters can override length
+        // numeric + nonNumeric can also override length, so max it with previous.
+        final int effectiveNonLetter = Math.max(nonLetter, indirectNonLetter);
+        final int effectiveNonNumeric = Math.max(nonNumeric, indirectNonNumeric);
+        final int indirectLength = Math.max(effectiveLetters + effectiveNonLetter,
+                numeric + effectiveNonNumeric);
+
+        if (indirectLetters >= letters) {
+            letters = 0;
+        }
+        if (indirectNonLetter >= nonLetter) {
+            nonLetter = 0;
+        }
+        if (indirectNonNumeric >= nonNumeric) {
+            nonNumeric = 0;
+        }
+        if (indirectLength >= length) {
+            length = 0;
+        }
+    }
+
+    /**
+     * Combine minimum metrics, set by admin, complexity set by the requester and actual entered
+     * password metrics to get resulting minimum metrics that the password has to satisfy. Always
+     * returns a new PasswordMetrics object.
+     *
+     * TODO: move to PasswordPolicy
+     */
+    private static PasswordMetrics applyComplexity(
+            PasswordMetrics adminMetrics, boolean isPin, ComplexityBucket bucket) {
+        final PasswordMetrics minMetrics = new PasswordMetrics(adminMetrics);
+
+        if (!bucket.canHaveSequence()) {
+            minMetrics.seqLength = Math.min(minMetrics.seqLength, MAX_ALLOWED_SEQUENCE);
+        }
+
+        minMetrics.length = Math.max(minMetrics.length, bucket.getMinimumLength(!isPin));
+
+        if (!isPin && !bucket.allowsNumericPassword()) {
+            minMetrics.nonNumeric = Math.max(minMetrics.nonNumeric, 1);
+        }
+
+        return minMetrics;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        final PasswordMetrics that = (PasswordMetrics) o;
+        return credType == that.credType
+                && length == that.length
+                && letters == that.letters
+                && upperCase == that.upperCase
+                && lowerCase == that.lowerCase
+                && numeric == that.numeric
+                && symbols == that.symbols
+                && nonLetter == that.nonLetter
+                && nonNumeric == that.nonNumeric
+                && seqLength == that.seqLength;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(credType, length, letters, upperCase, lowerCase, numeric, symbols,
+                nonLetter, nonNumeric, seqLength);
+    }
 }
diff --git a/core/java/android/app/admin/PasswordPolicy.java b/core/java/android/app/admin/PasswordPolicy.java
new file mode 100644
index 0000000..13f11ad
--- /dev/null
+++ b/core/java/android/app/admin/PasswordPolicy.java
@@ -0,0 +1,83 @@
+/*
+ * 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 android.app.admin;
+
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+
+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_PATTERN;
+
+/**
+ * {@hide}
+ */
+public class PasswordPolicy {
+    public static final int DEF_MINIMUM_LENGTH = 0;
+    public static final int DEF_MINIMUM_LETTERS = 1;
+    public static final int DEF_MINIMUM_UPPER_CASE = 0;
+    public static final int DEF_MINIMUM_LOWER_CASE = 0;
+    public static final int DEF_MINIMUM_NUMERIC = 1;
+    public static final int DEF_MINIMUM_SYMBOLS = 1;
+    public static final int DEF_MINIMUM_NON_LETTER = 0;
+
+    public int quality = PASSWORD_QUALITY_UNSPECIFIED;
+    public int length = DEF_MINIMUM_LENGTH;
+    public int letters = DEF_MINIMUM_LETTERS;
+    public int upperCase = DEF_MINIMUM_UPPER_CASE;
+    public int lowerCase = DEF_MINIMUM_LOWER_CASE;
+    public int numeric = DEF_MINIMUM_NUMERIC;
+    public int symbols = DEF_MINIMUM_SYMBOLS;
+    public int nonLetter = DEF_MINIMUM_NON_LETTER;
+
+    /**
+     * Returns a minimum password metrics that the password should have to satisfy current policy.
+     */
+    public PasswordMetrics getMinMetrics() {
+        if (quality == PASSWORD_QUALITY_UNSPECIFIED) {
+            return new PasswordMetrics(CREDENTIAL_TYPE_NONE);
+        } else if (quality == PASSWORD_QUALITY_BIOMETRIC_WEAK
+                || quality == PASSWORD_QUALITY_SOMETHING) {
+            return new PasswordMetrics(CREDENTIAL_TYPE_PATTERN);
+        } // quality is NUMERIC or stronger.
+
+        PasswordMetrics result = new PasswordMetrics(CREDENTIAL_TYPE_PASSWORD);
+        result.length = length;
+
+        if (quality == PASSWORD_QUALITY_NUMERIC_COMPLEX) {
+            result.seqLength = PasswordMetrics.MAX_ALLOWED_SEQUENCE;
+        } else if (quality == PASSWORD_QUALITY_ALPHABETIC) {
+            result.nonNumeric = 1;
+        } else if (quality == PASSWORD_QUALITY_ALPHANUMERIC) {
+            result.numeric = 1;
+            result.nonNumeric = 1;
+        } else if (quality == PASSWORD_QUALITY_COMPLEX) {
+            result.numeric = numeric;
+            result.letters = letters;
+            result.upperCase = upperCase;
+            result.lowerCase = lowerCase;
+            result.nonLetter = nonLetter;
+            result.symbols = symbols;
+        }
+        return result;
+    }
+}
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 955093d..90ecce2 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -390,6 +390,8 @@
             }
             Bundle extras = new Bundle();
             extras.putParcelable(SliceProvider.EXTRA_INTENT, intent);
+            extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS,
+                    new ArrayList<>(supportedSpecs));
             final Bundle res = provider.call(SliceProvider.METHOD_MAP_INTENT, null, extras);
             if (res == null) {
                 return null;
diff --git a/core/java/android/app/timedetector/TimeSignal.java b/core/java/android/app/timedetector/TimeSignal.java
index da21794..b494260 100644
--- a/core/java/android/app/timedetector/TimeSignal.java
+++ b/core/java/android/app/timedetector/TimeSignal.java
@@ -56,8 +56,7 @@
 
     private static TimeSignal createFromParcel(Parcel in) {
         String sourceId = in.readString();
-        TimestampedValue<Long> utcTime =
-                TimestampedValue.readFromParcel(in, null /* classLoader */, Long.class);
+        TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
         return new TimeSignal(sourceId, utcTime);
     }
 
@@ -69,7 +68,7 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeString(mSourceId);
-        TimestampedValue.writeToParcel(dest, mUtcTime);
+        dest.writeParcelable(mUtcTime, 0);
     }
 
     @NonNull
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index b3260c4..024afe2 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -154,12 +154,6 @@
     public abstract int[] getIdleUidsForUser(@UserIdInt int userId);
 
     /**
-     * @return True if currently app idle parole mode is on.  This means all idle apps are allow to
-     * run for a short period of time.
-     */
-    public abstract boolean isAppIdleParoleOn();
-
-    /**
      * Sets up a listener for changes to packages being accessed.
      * @param listener A listener within the system process.
      */
@@ -180,12 +174,6 @@
                 boolean idle, int bucket, int reason);
 
         /**
-         * Callback to inform listeners that the parole state has changed. This means apps are
-         * allowed to do work even if they're idle or in a low bucket.
-         */
-        public abstract void onParoleStateChanged(boolean isParoleOn);
-
-        /**
          * Optional callback to inform the listener that the app has transitioned into
          * an active state due to user interaction.
          */
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 9dbfbc7..02b6b3e 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -1469,9 +1469,8 @@
      * This method can be called from multiple threads, as described in
      * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
      * and Threads</a>.
-     * @param uri The content:// URI of the insertion request. This must not be {@code null}.
+     * @param uri The content:// URI of the insertion request.
      * @param values A set of column_name/value pairs to add to the database.
-     *     This must not be {@code null}.
      * @return The URI for the newly inserted item.
      */
     @Override
@@ -1538,7 +1537,6 @@
      * @param uri The URI to query. This can potentially have a record ID if this
      * is an update request for a specific record.
      * @param values A set of column_name/value pairs to update in the database.
-     *     This must not be {@code null}.
      * @param selection An optional filter to match rows to update.
      * @return the number of rows affected.
      */
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 7c279fe..7f9ea76 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1765,7 +1765,7 @@
             stableProvider = null;
 
             return new AssetFileDescriptor(pfd, fd.getStartOffset(),
-                    fd.getDeclaredLength());
+                    fd.getDeclaredLength(), fd.getExtras());
 
         } catch (RemoteException e) {
             // Whatever, whatever, we'll go away.
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 227684b..0aab208 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -63,6 +63,7 @@
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 import android.provider.MediaStore;
+import android.telephony.TelephonyRegistryManager;
 import android.util.AttributeSet;
 import android.view.Display;
 import android.view.DisplayAdjustments;
@@ -810,6 +811,17 @@
         throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
 
+    /**
+     * <p>Features are used in complex apps to logically separate parts of the app. E.g. a
+     * blogging app might also have a instant messaging app built in.
+     *
+     * @return the feature id this context is for or {@code null} if this is the default
+     * feature.
+     */
+    public @Nullable String getFeatureId() {
+        return null;
+    }
+
     /** Return the full application info for this context's package. */
     public abstract ApplicationInfo getApplicationInfo();
 
@@ -4716,7 +4728,7 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve an
-     * {@link android.os.telephony.TelephonyRegistryManager}.
+     * {@link TelephonyRegistryManager}.
      * @hide
      */
     @SystemApi
@@ -5244,7 +5256,7 @@
     @SystemApi
     @TestApi
     @NonNull
-    public Context createContextAsUser(@NonNull UserHandle user) {
+    public Context createContextAsUser(@NonNull UserHandle user, @CreatePackageOptions int flags) {
         if (Build.IS_ENG) {
             throw new IllegalStateException("createContextAsUser not overridden!");
         }
@@ -5331,6 +5343,20 @@
     public abstract Context createDisplayContext(@NonNull Display display);
 
     /**
+     * Return a new Context object for the current Context but for a different feature in the app.
+     * Features can be used by complex apps to separate logical parts.
+     *
+     * @param featureId The feature id or {@code null} to create a context for the default feature.
+     *
+     * @return A {@link Context} for the feature
+     *
+     * @see #getFeatureId()
+     */
+    public @NonNull Context createFeatureContext(@Nullable String featureId) {
+        return this;
+    }
+
+    /**
      * Return a new Context object for the current Context but whose storage
      * APIs are backed by device-protected storage.
      * <p>
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index f7cd51e..d5d0dce 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
@@ -158,6 +159,12 @@
         return mBase.getOpPackageName();
     }
 
+    /** @hide */
+    @Override
+    public @Nullable String getFeatureId() {
+        return mBase.getFeatureId();
+    }
+
     @Override
     public ApplicationInfo getApplicationInfo() {
         return mBase.getApplicationInfo();
@@ -885,8 +892,8 @@
 
     /** @hide */
     @Override
-    public Context createContextAsUser(UserHandle user) {
-        return mBase.createContextAsUser(user);
+    public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) {
+        return mBase.createContextAsUser(user, flags);
     }
 
     /** @hide */
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index c3daad1..85f96fc 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -401,7 +401,8 @@
         }
 
         if (forDataDelivery) {
-            if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid, message)
+            // TODO moltmann: Set correct feature id
+            if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid, null, message)
                     != AppOpsManager.MODE_ALLOWED) {
                 return PERMISSION_DENIED_APP_OP;
             }
@@ -414,4 +415,4 @@
 
         return PERMISSION_GRANTED;
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/android/content/pm/AndroidTestBaseUpdater.java b/core/java/android/content/pm/AndroidTestBaseUpdater.java
index 8fcfe71..18d3ba3 100644
--- a/core/java/android/content/pm/AndroidTestBaseUpdater.java
+++ b/core/java/android/content/pm/AndroidTestBaseUpdater.java
@@ -55,15 +55,20 @@
     private static final long REMOVE_ANDROID_TEST_BASE = 133396946L;
 
     private static boolean isChangeEnabled(Package pkg) {
-        IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
-                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
-        try {
-            return platformCompat.isChangeEnabled(REMOVE_ANDROID_TEST_BASE, pkg.applicationInfo);
-        } catch (RemoteException | NullPointerException e) {
-            Log.e(TAG, "Failed to get a response from PLATFORM_COMPAT_SERVICE", e);
+        // Do not ask platform compat for system apps to prevent a boot time regression in tests.
+        // b/142558883.
+        if (!pkg.applicationInfo.isSystemApp()) {
+            IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
+                    ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+            try {
+                return platformCompat.isChangeEnabled(REMOVE_ANDROID_TEST_BASE,
+                        pkg.applicationInfo);
+            } catch (RemoteException | NullPointerException e) {
+                Log.e(TAG, "Failed to get a response from PLATFORM_COMPAT_SERVICE", e);
+            }
         }
         // Fall back to previous behaviour.
-        return pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.Q;
+        return pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.Q;
     }
 
     @Override
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 19d8edf..1d78e2c 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -682,6 +682,8 @@
 
     String getWellbeingPackageName();
 
+    String[] getTelephonyPackageNames();
+
     String getAppPredictionServicePackageName();
 
     String getSystemCaptionsServicePackageName();
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 69ce3bd..edc66c5 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -349,14 +349,7 @@
      */
     public int createSession(@NonNull SessionParams params) throws IOException {
         try {
-            final String installerPackage;
-            if (params.installerPackageName == null) {
-                installerPackage = mInstallerPackageName;
-            } else {
-                installerPackage = params.installerPackageName;
-            }
-
-            return mInstaller.createSession(params, installerPackage, mUserId);
+            return mInstaller.createSession(params, mInstallerPackageName, mUserId);
         } catch (RuntimeException e) {
             ExceptionUtils.maybeUnwrapIOException(e);
             throw e;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 9513ce8..7509065 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2858,6 +2858,14 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+     * The device does not have slices implementation.
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_SLICES_DISABLED = "android.software.slices_disabled";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
      * The device supports device-unique Keystore attestations.  Only available on devices that
      * also support {@link #FEATURE_STRONGBOX_KEYSTORE}, and can only be used by device owner
      * apps (see {@link android.app.admin.DevicePolicyManager#generateKeyPair}).
@@ -7416,6 +7424,18 @@
     }
 
     /**
+     * @return the system defined telephony package names, or null if there's none.
+     *
+     * @hide
+     */
+    @Nullable
+    @TestApi
+    public String[] getTelephonyPackageNames() {
+        throw new UnsupportedOperationException(
+                "getTelephonyPackageNames not implemented in subclass");
+    }
+
+    /**
      * @return the system defined content capture service package name, or null if there's none.
      *
      * @hide
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 0b157fa..cf21e96 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -577,8 +577,6 @@
      */
     public interface Callback {
         boolean hasFeature(String feature);
-        String[] getOverlayPaths(String targetPackageName, String targetPath);
-        String[] getOverlayApks(String targetPackageName);
     }
 
     /**
@@ -595,14 +593,6 @@
         @Override public boolean hasFeature(String feature) {
             return mPm.hasSystemFeature(feature);
         }
-
-        @Override public String[] getOverlayPaths(String targetPackageName, String targetPath) {
-            return null;
-        }
-
-        @Override public String[] getOverlayApks(String targetPackageName) {
-            return null;
-        }
     }
 
     /**
@@ -1195,19 +1185,7 @@
             }
 
             final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
-            Package p = fromCacheEntry(bytes);
-            if (mCallback != null) {
-                String[] overlayApks = mCallback.getOverlayApks(p.packageName);
-                if (overlayApks != null && overlayApks.length > 0) {
-                    for (String overlayApk : overlayApks) {
-                        // If a static RRO is updated, return null.
-                        if (!isCacheUpToDate(new File(overlayApk), cacheFile)) {
-                            return null;
-                        }
-                    }
-                }
-            }
-            return p;
+            return fromCacheEntry(bytes);
         } catch (Throwable e) {
             Slog.w(TAG, "Error reading package cache: ", e);
 
@@ -1381,7 +1359,7 @@
             final Resources res = new Resources(assets, mMetrics, null);
 
             final String[] outError = new String[1];
-            final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
+            final Package pkg = parseBaseApk(res, parser, flags, outError);
             if (pkg == null) {
                 throw new PackageParserException(mParseError,
                         apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
@@ -1944,7 +1922,6 @@
      * need to consider whether they should be supported by split APKs and child
      * packages.
      *
-     * @param apkPath The package apk file path
      * @param res The resources from which to resolve values
      * @param parser The manifest parser
      * @param flags Flags how to parse
@@ -1954,8 +1931,7 @@
      * @throws XmlPullParserException
      * @throws IOException
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
+    private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
             String[] outError) throws XmlPullParserException, IOException {
         final String splitName;
         final String pkgName;
@@ -1975,15 +1951,6 @@
             return null;
         }
 
-        if (mCallback != null) {
-            String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
-            if (overlayPaths != null && overlayPaths.length > 0) {
-                for (String overlayPath : overlayPaths) {
-                    res.getAssets().addOverlayPath(overlayPath);
-                }
-            }
-        }
-
         final Package pkg = new Package(pkgName);
 
         TypedArray sa = res.obtainAttributes(parser,
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index dd5c6a5..aa6f58e 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -237,6 +237,28 @@
     @TestApi
     public static final int PROTECTION_FLAG_APP_PREDICTOR = 0x200000;
 
+    /**
+     * Additional flag for {@link #protectionLevel}, corresponding
+     * to the <code>telephony</code> value of
+     * {@link android.R.attr#protectionLevel}.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int PROTECTION_FLAG_TELEPHONY = 0x400000;
+
+    /**
+     * Additional flag for {@link #protectionLevel}, corresponding
+     * to the <code>wifi</code> value of
+     * {@link android.R.attr#protectionLevel}.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int PROTECTION_FLAG_WIFI = 0x800000;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = {
             PROTECTION_FLAG_PRIVILEGED,
@@ -258,6 +280,8 @@
             PROTECTION_FLAG_CONFIGURATOR,
             PROTECTION_FLAG_INCIDENT_REPORT_APPROVER,
             PROTECTION_FLAG_APP_PREDICTOR,
+            PROTECTION_FLAG_TELEPHONY,
+            PROTECTION_FLAG_WIFI,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ProtectionFlags {}
@@ -501,6 +525,12 @@
         if ((level & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0) {
             protLevel += "|appPredictor";
         }
+        if ((level & PermissionInfo.PROTECTION_FLAG_TELEPHONY) != 0) {
+            protLevel += "|telephony";
+        }
+        if ((level & PermissionInfo.PROTECTION_FLAG_WIFI) != 0) {
+            protLevel += "|wifi";
+        }
         return protLevel;
     }
 
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 5c65238..cfa3934 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -473,6 +473,14 @@
     public static final int TETHERING_BLUETOOTH = 2;
 
     /**
+     * Wifi P2p tethering type.
+     * Wifi P2p tethering is set through events automatically, and don't
+     * need to start from #startTethering(int, boolean, OnStartTetheringCallback).
+     * @hide
+     */
+    public static final int TETHERING_WIFI_P2P = 3;
+
+    /**
      * Extra used for communicating with the TetherService. Includes the type of tethering to
      * enable if any.
      * @hide
diff --git a/core/java/android/net/INetworkPolicyListener.aidl b/core/java/android/net/INetworkPolicyListener.aidl
index 106b7be..fe9141c 100644
--- a/core/java/android/net/INetworkPolicyListener.aidl
+++ b/core/java/android/net/INetworkPolicyListener.aidl
@@ -15,6 +15,7 @@
  */
 
 package android.net;
+import android.telephony.SubscriptionPlan;
 
 /** {@hide} */
 oneway interface INetworkPolicyListener {
@@ -22,5 +23,6 @@
     void onMeteredIfacesChanged(in String[] meteredIfaces);
     void onRestrictBackgroundChanged(boolean restrictBackground);
     void onUidPoliciesChanged(int uid, int uidPolicies);
-    void onSubscriptionOverride(int subId, int overrideMask, int overrideValue, long networkTypeMask);
+    void onSubscriptionOverride(int subId, int overrideMask, int overrideValue);
+    void onSubscriptionPlansChanged(int subId, in SubscriptionPlan[] plans);
 }
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 90327663..385cb1d 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -76,7 +76,7 @@
     SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage);
     void setSubscriptionPlans(int subId, in SubscriptionPlan[] plans, String callingPackage);
     String getSubscriptionPlansOwner(int subId);
-    void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, long networkTypeMask, long timeoutMillis, String callingPackage);
+    void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, long timeoutMillis, String callingPackage);
 
     void factoryReset(String subscriber);
 
diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java
index 2cf2a65..8729514 100644
--- a/core/java/android/net/MacAddress.java
+++ b/core/java/android/net/MacAddress.java
@@ -416,7 +416,6 @@
      * @param mask MacAddress representing the mask to use during comparison.
      * @return true if this MAC Address matches the given range.
      *
-     * @hide
      */
     public boolean matches(@NonNull MacAddress baseAddress, @NonNull MacAddress mask) {
         Preconditions.checkNotNull(baseAddress);
@@ -430,7 +429,6 @@
      * IPv6 address per RFC 4862.
      *
      * @return A link-local Inet6Address constructed from the MAC address.
-     * @hide
      */
     public @Nullable Inet6Address getLinkLocalIpv6FromEui48Mac() {
         byte[] macEui48Bytes = toByteArray();
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 628dcd2..9150aae 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -31,6 +31,7 @@
 import android.os.Build;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.telephony.SubscriptionPlan;
 import android.util.DebugUtils;
 import android.util.Pair;
 import android.util.Range;
@@ -380,7 +381,8 @@
         @Override public void onMeteredIfacesChanged(String[] meteredIfaces) { }
         @Override public void onRestrictBackgroundChanged(boolean restrictBackground) { }
         @Override public void onUidPoliciesChanged(int uid, int uidPolicies) { }
-        @Override public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue,
-                long networkTypeMask) { }
+        @Override public void onSubscriptionOverride(int subId, int overrideMask,
+                int overrideValue) { }
+        @Override public void onSubscriptionPlansChanged(int subId, SubscriptionPlan[] plans) { }
     }
 }
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 2c9333b..ef3afab 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -1085,4 +1085,13 @@
         StrictMode.clearGatheredViolations();
         return res;
     }
+
+    /**
+     * Returns the specified service from servicemanager. If the service is not running,
+     * servicemanager will attempt to start it, and this function will wait for it to be ready.
+     * Returns nullptr only if there are permission problems or fatal errors.
+     * @hide
+     */
+    public static final native @Nullable IBinder waitForService(@NonNull String serviceName)
+            throws RemoteException;
 }
diff --git a/core/java/android/os/ConfigUpdate.java b/core/java/android/os/ConfigUpdate.java
index 767c15c..9c999b2 100644
--- a/core/java/android/os/ConfigUpdate.java
+++ b/core/java/android/os/ConfigUpdate.java
@@ -113,6 +113,21 @@
     public static final String ACTION_UPDATE_CARRIER_ID_DB
             = "android.os.action.UPDATE_CARRIER_ID_DB";
 
+    /**
+    * Broadcast intent action indicating that the updated emergency number database is available.
+    * <p>Extra: "VERSION" the numeric version of the new data. Devices should only install if the
+    * update version is newer than the current one.
+    * <p>Extra: "REQUIRED_HASH" the hash of the current update data.
+    * <p>Input: {@link android.content.Intent#getData} is URI of downloaded emergency number file.
+    * Devices should pick up the downloaded file and persist to the database
+    * {@code com.android.internal.telephony.emergency.EmergencyNumberTracker}.
+    *
+    * @hide
+    */
+    @SystemApi
+    public static final String ACTION_UPDATE_EMERGENCY_NUMBER_DB =
+            "android.os.action.UPDATE_EMERGENCY_NUMBER_DB";
+
     private ConfigUpdate() {
     }
 }
diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl
index 654b0f7..26c1ec1 100644
--- a/core/java/android/permission/IPermissionController.aidl
+++ b/core/java/android/permission/IPermissionController.aidl
@@ -31,8 +31,8 @@
     void revokeRuntimePermissions(in Bundle request, boolean doDryRun, int reason,
             String callerPackageName, in AndroidFuture callback);
     void getRuntimePermissionBackup(in UserHandle user, in ParcelFileDescriptor pipe);
-    void restoreRuntimePermissionBackup(in UserHandle user, in ParcelFileDescriptor pipe);
-    void restoreDelayedRuntimePermissionBackup(String packageName, in UserHandle user,
+    void stageAndApplyRuntimePermissionsBackup(in UserHandle user, in ParcelFileDescriptor pipe);
+    void applyStagedRuntimePermissionBackup(String packageName, in UserHandle user,
             in AndroidFuture callback);
     void getAppPermissions(String packageName, in AndroidFuture callback);
     void revokeRuntimePermission(String packageName, String permissionName);
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index 923d9f8..421e29e 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -62,6 +62,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -139,20 +140,6 @@
     }
 
     /**
-     * Callback for delivering the result of {@link #getRuntimePermissionBackup}.
-     *
-     * @hide
-     */
-    public interface OnGetRuntimePermissionBackupCallback {
-        /**
-         * The result for {@link #getRuntimePermissionBackup}.
-         *
-         * @param backup The backup file
-         */
-        void onGetRuntimePermissionsBackup(@NonNull byte[] backup);
-    }
-
-    /**
      * Callback for delivering the result of {@link #getAppPermissions}.
      *
      * @hide
@@ -246,6 +233,24 @@
     }
 
     /**
+     * Throw a {@link SecurityException} if not at least one of the permissions is granted.
+     *
+     * @param requiredPermissions A list of permissions. Any of of them if sufficient to pass the
+     *                            check
+     */
+    private void enforceSomePermissionsGrantedToSelf(@NonNull String... requiredPermissions) {
+        for (String requiredPermission : requiredPermissions) {
+            if (mContext.checkSelfPermission(requiredPermission)
+                    == PackageManager.PERMISSION_GRANTED) {
+                return;
+            }
+        }
+
+        throw new SecurityException("At lest one of the following permissions is required: "
+                + Arrays.toString(requiredPermissions));
+    }
+
+    /**
      * Revoke a set of runtime permissions for various apps.
      *
      * @param request The permissions to revoke as {@code Map<packageName, List<permission>>}
@@ -268,11 +273,7 @@
         }
 
         // Check required permission to fail immediately instead of inside the oneway binder call
-        if (mContext.checkSelfPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
-                    + " required");
-        }
+        enforceSomePermissionsGrantedToSelf(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
 
         mRemoteService.postAsync(service -> {
             Bundle bundledizedRequest = new Bundle();
@@ -358,46 +359,61 @@
      *
      * @param user The user to be backed up
      * @param executor Executor on which to invoke the callback
-     * @param callback Callback to receive the result
-     *
-     * @hide
+     * @param callback Callback to receive the result. The resulting backup-file is opaque and no
+     *                 guarantees are made other than that the file can be send to
+     *                 {@link #restoreRuntimePermissionBackup} in this and future versions of
+     *                 Android.
      */
     @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
     public void getRuntimePermissionBackup(@NonNull UserHandle user,
             @NonNull @CallbackExecutor Executor executor,
-            @NonNull OnGetRuntimePermissionBackupCallback callback) {
+            @NonNull Consumer<byte[]> callback) {
         checkNotNull(user);
         checkNotNull(executor);
         checkNotNull(callback);
 
+        // Check required permission to fail immediately instead of inside the oneway binder call
+        enforceSomePermissionsGrantedToSelf(Manifest.permission.GET_RUNTIME_PERMISSIONS);
+
         mRemoteService.postAsync(service -> RemoteStream.receiveBytes(remotePipe -> {
             service.getRuntimePermissionBackup(user, remotePipe);
         })).whenCompleteAsync((bytes, err) -> {
             if (err != null) {
                 Log.e(TAG, "Error getting permission backup", err);
-                callback.onGetRuntimePermissionsBackup(EmptyArray.BYTE);
+                callback.accept(EmptyArray.BYTE);
             } else {
-                callback.onGetRuntimePermissionsBackup(bytes);
+                callback.accept(bytes);
             }
         }, executor);
     }
 
     /**
-     * Restore a backup of the runtime permissions.
+     * Restore a {@link #getRuntimePermissionBackup backup-file} of the runtime permissions.
      *
-     * @param backup the backup to restore. The backup is sent asynchronously, hence it should not
-     *               be modified after calling this method.
+     * <p>This might leave some part of the backup-file unapplied if an package mentioned in the
+     * backup-file is not yet installed. It is required that
+     * {@link #applyStagedRuntimePermissionBackup} is called after any package is installed to
+     * apply the rest of the backup-file.
+     *
+     * @param backup the backup-file to restore. The backup is sent asynchronously, hence it should
+     *               not be modified after calling this method.
      * @param user The user to be restore
-     *
-     * @hide
      */
-    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
-    public void restoreRuntimePermissionBackup(@NonNull byte[] backup, @NonNull UserHandle user) {
+    @RequiresPermission(anyOf = {
+            Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+            Manifest.permission.RESTORE_RUNTIME_PERMISSIONS
+    })
+    public void stageAndApplyRuntimePermissionsBackup(@NonNull byte[] backup,
+            @NonNull UserHandle user) {
         checkNotNull(backup);
         checkNotNull(user);
 
+        // Check required permission to fail immediately instead of inside the oneway binder call
+        enforceSomePermissionsGrantedToSelf(Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+                Manifest.permission.RESTORE_RUNTIME_PERMISSIONS);
+
         mRemoteService.postAsync(service -> RemoteStream.sendBytes(remotePipe -> {
-            service.restoreRuntimePermissionBackup(user, remotePipe);
+            service.stageAndApplyRuntimePermissionsBackup(user, remotePipe);
         }, backup))
                 .whenComplete((nullResult, err) -> {
                     if (err != null) {
@@ -407,17 +423,22 @@
     }
 
     /**
-     * Restore a backup of the runtime permissions that has been delayed.
+     * Restore unapplied parts of a {@link #stageAndApplyRuntimePermissionsBackup previously staged}
+     * backup-file of the runtime permissions.
+     *
+     * <p>This should be called every time after a package is installed until the callback
+     * reports that there is no more unapplied backup left.
      *
      * @param packageName The package that is ready to have it's permissions restored.
-     * @param user The user to restore
+     * @param user The user the package belongs to
      * @param executor Executor to execute the callback on
-     * @param callback Is called with {@code true} iff there is still more delayed backup left
-     *
-     * @hide
+     * @param callback Is called with {@code true} iff there is still more unapplied backup left
      */
-    @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
-    public void restoreDelayedRuntimePermissionBackup(@NonNull String packageName,
+    @RequiresPermission(anyOf = {
+            Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+            Manifest.permission.RESTORE_RUNTIME_PERMISSIONS
+    })
+    public void applyStagedRuntimePermissionBackup(@NonNull String packageName,
             @NonNull UserHandle user,
             @NonNull @CallbackExecutor Executor executor,
             @NonNull Consumer<Boolean> callback) {
@@ -426,13 +447,17 @@
         checkNotNull(executor);
         checkNotNull(callback);
 
+        // Check required permission to fail immediately instead of inside the oneway binder call
+        enforceSomePermissionsGrantedToSelf(Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+                Manifest.permission.RESTORE_RUNTIME_PERMISSIONS);
+
         mRemoteService.postAsync(service -> {
-            AndroidFuture<Boolean> restoreDelayedRuntimePermissionBackupResult =
+            AndroidFuture<Boolean> applyStagedRuntimePermissionBackupResult =
                     new AndroidFuture<>();
-            service.restoreDelayedRuntimePermissionBackup(packageName, user,
-                    restoreDelayedRuntimePermissionBackupResult);
-            return restoreDelayedRuntimePermissionBackupResult;
-        }).whenCompleteAsync((restoreDelayedRuntimePermissionBackupResult, err) -> {
+            service.applyStagedRuntimePermissionBackup(packageName, user,
+                    applyStagedRuntimePermissionBackupResult);
+            return applyStagedRuntimePermissionBackupResult;
+        }).whenCompleteAsync((applyStagedRuntimePermissionBackupResult, err) -> {
             long token = Binder.clearCallingIdentity();
             try {
                 if (err != null) {
@@ -440,7 +465,7 @@
                     callback.accept(true);
                 } else {
                     callback.accept(
-                            Boolean.TRUE.equals(restoreDelayedRuntimePermissionBackupResult));
+                            Boolean.TRUE.equals(applyStagedRuntimePermissionBackupResult));
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index 7363d77..8f765fa 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -54,6 +54,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
@@ -105,31 +106,54 @@
     public abstract void onGetRuntimePermissionsBackup(@NonNull UserHandle user,
             @NonNull OutputStream backup, @NonNull Runnable callback);
 
+
+    /**
+     * @deprecated Implement {@link #onStageAndApplyRuntimePermissionsBackup} instead
+     */
+    @Deprecated
+    @BinderThread
+    public void onRestoreRuntimePermissionsBackup(@NonNull UserHandle user,
+            @NonNull InputStream backup, @NonNull Runnable callback) {
+    }
+
     /**
      * Restore a backup of the runtime permissions.
      *
      * <p>If an app mentioned in the backup is not installed the state should be saved to later
-     * be restored via {@link #onRestoreDelayedRuntimePermissionsBackup}.
+     * be restored via {@link #onApplyStagedRuntimePermissionBackup}.
      *
      * @param user The user to restore
      * @param backup The stream to read the backup from
      * @param callback Callback waiting for operation to be complete
      */
     @BinderThread
-    public abstract void onRestoreRuntimePermissionsBackup(@NonNull UserHandle user,
-            @NonNull InputStream backup, @NonNull Runnable callback);
+    public void onStageAndApplyRuntimePermissionsBackup(@NonNull UserHandle user,
+            @NonNull InputStream backup, @NonNull Runnable callback) {
+        onRestoreRuntimePermissionsBackup(user, backup, callback);
+    }
+
+    /**
+     * @deprecated Implement {@link #onApplyStagedRuntimePermissionBackup} instead
+     */
+    @Deprecated
+    @BinderThread
+    public void onRestoreDelayedRuntimePermissionsBackup(@NonNull String packageName,
+            @NonNull UserHandle user, @NonNull Consumer<Boolean> callback) {
+    }
 
     /**
      * Restore the permission state of an app that was provided in
-     * {@link #onRestoreRuntimePermissionsBackup} but could not be restored back then.
+     * {@link #onStageAndApplyRuntimePermissionsBackup} but could not be restored back then.
      *
      * @param packageName The app to restore
      * @param user The user to restore
      * @param callback Callback waiting for whether there is still delayed backup left
      */
     @BinderThread
-    public abstract void onRestoreDelayedRuntimePermissionsBackup(@NonNull String packageName,
-            @NonNull UserHandle user, @NonNull Consumer<Boolean> callback);
+    public void onApplyStagedRuntimePermissionBackup(@NonNull String packageName,
+            @NonNull UserHandle user, @NonNull Consumer<Boolean> callback) {
+        onRestoreDelayedRuntimePermissionsBackup(packageName, user, callback);
+    }
 
     /**
      * Gets the runtime permissions for an app.
@@ -238,7 +262,8 @@
                     request.put(packageName, permissions);
                 }
 
-                enforceCallingPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, null);
+                enforceSomePermissionsGrantedToCaller(
+                        Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
 
                 // Verify callerPackageName
                 try {
@@ -258,12 +283,33 @@
                         });
             }
 
+            /**
+             * Throw a {@link SecurityException} if not at least one of the permissions is granted.
+             *
+             * @param requiredPermissions A list of permissions. Any of of them if sufficient to
+             *                            pass the check
+             */
+            private void enforceSomePermissionsGrantedToCaller(
+                    @NonNull String... requiredPermissions) {
+                for (String requiredPermission : requiredPermissions) {
+                    if (checkCallingPermission(requiredPermission)
+                            == PackageManager.PERMISSION_GRANTED) {
+                        return;
+                    }
+                }
+
+                throw new SecurityException(
+                        "At lest one of the following permissions is required: " + Arrays.toString(
+                                requiredPermissions));
+            }
+
+
             @Override
             public void getRuntimePermissionBackup(UserHandle user, ParcelFileDescriptor pipe) {
                 checkNotNull(user);
                 checkNotNull(pipe);
 
-                enforceCallingPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, null);
+                enforceSomePermissionsGrantedToCaller(Manifest.permission.GET_RUNTIME_PERMISSIONS);
 
                 try (OutputStream backup = new ParcelFileDescriptor.AutoCloseOutputStream(pipe)) {
                     CountDownLatch latch = new CountDownLatch(1);
@@ -277,15 +323,17 @@
             }
 
             @Override
-            public void restoreRuntimePermissionBackup(UserHandle user, ParcelFileDescriptor pipe) {
+            public void stageAndApplyRuntimePermissionsBackup(UserHandle user,
+                    ParcelFileDescriptor pipe) {
                 checkNotNull(user);
                 checkNotNull(pipe);
 
-                enforceCallingPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS, null);
+                enforceSomePermissionsGrantedToCaller(Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+                        Manifest.permission.RESTORE_RUNTIME_PERMISSIONS);
 
                 try (InputStream backup = new ParcelFileDescriptor.AutoCloseInputStream(pipe)) {
                     CountDownLatch latch = new CountDownLatch(1);
-                    onRestoreRuntimePermissionsBackup(user, backup, latch::countDown);
+                    onStageAndApplyRuntimePermissionsBackup(user, backup, latch::countDown);
                     latch.await();
                 } catch (IOException e) {
                     Log.e(LOG_TAG, "Could not open pipe to read backup from", e);
@@ -295,15 +343,16 @@
             }
 
             @Override
-            public void restoreDelayedRuntimePermissionBackup(String packageName, UserHandle user,
+            public void applyStagedRuntimePermissionBackup(String packageName, UserHandle user,
                     AndroidFuture callback) {
                 checkNotNull(packageName);
                 checkNotNull(user);
                 checkNotNull(callback);
 
-                enforceCallingPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS, null);
+                enforceSomePermissionsGrantedToCaller(Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+                        Manifest.permission.RESTORE_RUNTIME_PERMISSIONS);
 
-                onRestoreDelayedRuntimePermissionsBackup(packageName, user, callback::complete);
+                onApplyStagedRuntimePermissionBackup(packageName, user, callback::complete);
             }
 
             @Override
@@ -311,7 +360,7 @@
                 checkNotNull(packageName, "packageName");
                 checkNotNull(callback, "callback");
 
-                enforceCallingPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, null);
+                enforceSomePermissionsGrantedToCaller(Manifest.permission.GET_RUNTIME_PERMISSIONS);
 
                 onGetAppPermissions(packageName, callback::complete);
             }
@@ -321,7 +370,8 @@
                 checkNotNull(packageName, "packageName");
                 checkNotNull(permissionName, "permissionName");
 
-                enforceCallingPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, null);
+                enforceSomePermissionsGrantedToCaller(
+                        Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
 
                 CountDownLatch latch = new CountDownLatch(1);
                 PermissionControllerService.this.onRevokeRuntimePermission(packageName,
@@ -340,7 +390,7 @@
                 checkFlagsArgument(flags, COUNT_WHEN_SYSTEM | COUNT_ONLY_WHEN_GRANTED);
                 checkNotNull(callback, "callback");
 
-                enforceCallingPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, null);
+                enforceSomePermissionsGrantedToCaller(Manifest.permission.GET_RUNTIME_PERMISSIONS);
 
                 onCountPermissionApps(permissionNames, flags, callback::complete);
             }
@@ -351,7 +401,7 @@
                 checkArgumentNonnegative(numMillis);
                 checkNotNull(callback, "callback");
 
-                enforceCallingPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, null);
+                enforceSomePermissionsGrantedToCaller(Manifest.permission.GET_RUNTIME_PERMISSIONS);
 
                 onGetPermissionUsages(countSystem, numMillis, callback::complete);
             }
@@ -369,15 +419,17 @@
                 checkNotNull(callback);
 
                 if (grantState == PERMISSION_GRANT_STATE_DENIED) {
-                    enforceCallingPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS, null);
+                    enforceSomePermissionsGrantedToCaller(
+                            Manifest.permission.GRANT_RUNTIME_PERMISSIONS);
                 }
 
                 if (grantState == PERMISSION_GRANT_STATE_DENIED) {
-                    enforceCallingPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, null);
+                    enforceSomePermissionsGrantedToCaller(
+                            Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
                 }
 
-                enforceCallingPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
-                        null);
+                enforceSomePermissionsGrantedToCaller(
+                        Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
 
                 onSetRuntimePermissionGrantStateByDeviceAdmin(callerPackageName,
                         packageName, permission, grantState, callback::complete);
@@ -387,8 +439,8 @@
             public void grantOrUpgradeDefaultRuntimePermissions(@NonNull AndroidFuture callback) {
                 checkNotNull(callback, "callback");
 
-                enforceCallingPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
-                        null);
+                enforceSomePermissionsGrantedToCaller(
+                        Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
 
                 onGrantOrUpgradeDefaultRuntimePermissions(() -> callback.complete(true));
             }
diff --git a/core/java/android/print/TEST_MAPPING b/core/java/android/print/TEST_MAPPING
new file mode 100644
index 0000000..4fa8822
--- /dev/null
+++ b/core/java/android/print/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsPrintTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        }
+      ]
+    }
+  ]
+}
diff --git a/core/java/android/print/pdf/TEST_MAPPING b/core/java/android/print/pdf/TEST_MAPPING
new file mode 100644
index 0000000..d763598
--- /dev/null
+++ b/core/java/android/print/pdf/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsPdfTestCases"
+    }
+  ]
+}
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index fd81178..eb09930 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -363,15 +363,22 @@
          * <p>
          * Type: INTEGER (int)
          *
-         * @see #FLAG_SUPPORTS_WRITE
-         * @see #FLAG_SUPPORTS_DELETE
-         * @see #FLAG_SUPPORTS_THUMBNAIL
+         * @see #FLAG_DIR_BLOCKS_TREE
          * @see #FLAG_DIR_PREFERS_GRID
          * @see #FLAG_DIR_PREFERS_LAST_MODIFIED
-         * @see #FLAG_VIRTUAL_DOCUMENT
+         * @see #FLAG_DIR_SUPPORTS_CREATE
+         * @see #FLAG_PARTIAL
          * @see #FLAG_SUPPORTS_COPY
+         * @see #FLAG_SUPPORTS_DELETE
+         * @see #FLAG_SUPPORTS_METADATA
          * @see #FLAG_SUPPORTS_MOVE
          * @see #FLAG_SUPPORTS_REMOVE
+         * @see #FLAG_SUPPORTS_RENAME
+         * @see #FLAG_SUPPORTS_SETTINGS
+         * @see #FLAG_SUPPORTS_THUMBNAIL
+         * @see #FLAG_SUPPORTS_WRITE
+         * @see #FLAG_VIRTUAL_DOCUMENT
+         * @see #FLAG_WEB_LINKABLE
          */
         public static final String COLUMN_FLAGS = "flags";
 
@@ -542,6 +549,23 @@
          * @see DocumentsContract#getDocumentMetadata(ContentInterface, Uri)
          */
         public static final int FLAG_SUPPORTS_METADATA = 1 << 14;
+
+        /**
+         * Flag indicating that a document is a directory that wants to block itself
+         * from being selected when the user launches an {@link Intent#ACTION_OPEN_DOCUMENT_TREE}
+         * intent. Only valid when {@link #COLUMN_MIME_TYPE} is {@link #MIME_TYPE_DIR}.
+         * <p>
+         * Note that this flag <em>only</em> applies to the single directory to which it is
+         * applied. It does <em>not</em> block the user from selecting either a parent or
+         * child directory during an {@link Intent#ACTION_OPEN_DOCUMENT_TREE} request.
+         * In particular, the only way to guarantee that a specific directory can never
+         * be granted via an {@link Intent#ACTION_OPEN_DOCUMENT_TREE} request is to ensure
+         * that both it and <em>all of its parent directories</em> have set this flag.
+         *
+         * @see Intent#ACTION_OPEN_DOCUMENT_TREE
+         * @see #COLUMN_FLAGS
+         */
+        public static final int FLAG_DIR_BLOCKS_TREE = 1 << 15;
     }
 
     /**
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 493f9a2..a1333df 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -39,7 +39,6 @@
 import android.content.Intent;
 import android.content.UriPermission;
 import android.database.Cursor;
-import android.database.DatabaseUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.ImageDecoder;
@@ -70,15 +69,19 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import libcore.util.HexEncoding;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Locale;
 import java.util.Objects;
 import java.util.Set;
 import java.util.regex.Pattern;
@@ -2059,7 +2062,17 @@
             /**
              * A non human readable key calculated from the TITLE, used for
              * searching, sorting and grouping
+             *
+             * @see Audio#keyFor(String)
+             * @deprecated These keys are generated using
+             *             {@link java.util.Locale#ROOT}, which means they don't
+             *             reflect locale-specific sorting preferences. To apply
+             *             locale-specific sorting preferences, use
+             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
+             *             {@code COLLATE LOCALIZED}, or
+             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
              */
+            @Deprecated
             @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
             public static final String TITLE_KEY = "title_key";
 
@@ -2104,7 +2117,17 @@
             /**
              * A non human readable key calculated from the ARTIST, used for
              * searching, sorting and grouping
+             *
+             * @see Audio#keyFor(String)
+             * @deprecated These keys are generated using
+             *             {@link java.util.Locale#ROOT}, which means they don't
+             *             reflect locale-specific sorting preferences. To apply
+             *             locale-specific sorting preferences, use
+             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
+             *             {@code COLLATE LOCALIZED}, or
+             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
              */
+            @Deprecated
             @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
             public static final String ARTIST_KEY = "artist_key";
 
@@ -2129,7 +2152,17 @@
             /**
              * A non human readable key calculated from the ALBUM, used for
              * searching, sorting and grouping
+             *
+             * @see Audio#keyFor(String)
+             * @deprecated These keys are generated using
+             *             {@link java.util.Locale#ROOT}, which means they don't
+             *             reflect locale-specific sorting preferences. To apply
+             *             locale-specific sorting preferences, use
+             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
+             *             {@code COLLATE LOCALIZED}, or
+             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
              */
+            @Deprecated
             @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
             public static final String ALBUM_KEY = "album_key";
 
@@ -2186,91 +2219,89 @@
             public static final String IS_AUDIOBOOK = "is_audiobook";
 
             /**
-             * The genre of the audio file, if any
-             * Does not exist in the database - only used by the media scanner for inserts.
-             * @hide
+             * The id of the genre the audio file is from, if any
              */
-            @Deprecated
-            // @Column(Cursor.FIELD_TYPE_STRING)
+            @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
+            public static final String GENRE_ID = "genre_id";
+
+            /**
+             * The genre of the audio file, if any.
+             */
+            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
             public static final String GENRE = "genre";
 
             /**
-             * The resource URI of a localized title, if any
+             * A non human readable key calculated from the GENRE, used for
+             * searching, sorting and grouping
+             *
+             * @see Audio#keyFor(String)
+             * @deprecated These keys are generated using
+             *             {@link java.util.Locale#ROOT}, which means they don't
+             *             reflect locale-specific sorting preferences. To apply
+             *             locale-specific sorting preferences, use
+             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
+             *             {@code COLLATE LOCALIZED}, or
+             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
+             */
+            @Deprecated
+            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+            public static final String GENRE_KEY = "genre_key";
+
+            /**
+             * The resource URI of a localized title, if any.
+             * <p>
              * Conforms to this pattern:
-             *   Scheme: {@link ContentResolver.SCHEME_ANDROID_RESOURCE}
-             *   Authority: Package Name of ringtone title provider
-             *   First Path Segment: Type of resource (must be "string")
-             *   Second Path Segment: Resource ID of title
-             * @hide
+             * <ul>
+             * <li>Scheme: {@link ContentResolver#SCHEME_ANDROID_RESOURCE}
+             * <li>Authority: Package Name of ringtone title provider
+             * <li>First Path Segment: Type of resource (must be "string")
+             * <li>Second Path Segment: Resource ID of title
+             * </ul>
              */
             @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
             public static final String TITLE_RESOURCE_URI = "title_resource_uri";
         }
 
+        private static final Pattern PATTERN_TRIM_BEFORE = Pattern.compile(
+                "(?i)(^(the|an|a) |,\\s*(the|an|a)$|[^\\w\\s]|^\\s+|\\s+$)");
+        private static final Pattern PATTERN_TRIM_AFTER = Pattern.compile(
+                "(^(00)+|(00)+$)");
+
         /**
-         * Converts a name to a "key" that can be used for grouping, sorting
-         * and searching.
-         * The rules that govern this conversion are:
-         * - remove 'special' characters like ()[]'!?.,
-         * - remove leading/trailing spaces
-         * - convert everything to lowercase
-         * - remove leading "the ", "an " and "a "
-         * - remove trailing ", the|an|a"
-         * - remove accents. This step leaves us with CollationKey data,
-         *   which is not human readable
+         * Converts a user-visible string into a "key" that can be used for
+         * grouping, sorting, and searching.
          *
-         * @param name The artist or album name to convert
-         * @return The "key" for the given name.
+         * @return Opaque token that should not be parsed or displayed to users.
+         * @deprecated These keys are generated using
+         *             {@link java.util.Locale#ROOT}, which means they don't
+         *             reflect locale-specific sorting preferences. To apply
+         *             locale-specific sorting preferences, use
+         *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
+         *             {@code COLLATE LOCALIZED}, or
+         *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
          */
-        public static String keyFor(String name) {
-            if (name != null)  {
-                boolean sortfirst = false;
-                if (name.equals(UNKNOWN_STRING)) {
-                    return "\001";
-                }
-                // Check if the first character is \001. We use this to
-                // force sorting of certain special files, like the silent ringtone.
-                if (name.startsWith("\001")) {
-                    sortfirst = true;
-                }
-                name = name.trim().toLowerCase();
-                if (name.startsWith("the ")) {
-                    name = name.substring(4);
-                }
-                if (name.startsWith("an ")) {
-                    name = name.substring(3);
-                }
-                if (name.startsWith("a ")) {
-                    name = name.substring(2);
-                }
-                if (name.endsWith(", the") || name.endsWith(",the") ||
-                    name.endsWith(", an") || name.endsWith(",an") ||
-                    name.endsWith(", a") || name.endsWith(",a")) {
-                    name = name.substring(0, name.lastIndexOf(','));
-                }
-                name = name.replaceAll("[\\[\\]\\(\\)\"'.,?!]", "").trim();
-                if (name.length() > 0) {
-                    // Insert a separator between the characters to avoid
-                    // matches on a partial character. If we ever change
-                    // to start-of-word-only matches, this can be removed.
-                    StringBuilder b = new StringBuilder();
-                    b.append('.');
-                    int nl = name.length();
-                    for (int i = 0; i < nl; i++) {
-                        b.append(name.charAt(i));
-                        b.append('.');
-                    }
-                    name = b.toString();
-                    String key = DatabaseUtils.getCollationKey(name);
-                    if (sortfirst) {
-                        key = "\001" + key;
-                    }
-                    return key;
-               } else {
-                    return "";
-                }
+        @Deprecated
+        public static @Nullable String keyFor(@Nullable String name) {
+            if (TextUtils.isEmpty(name)) return null;
+
+            if (UNKNOWN_STRING.equals(name)) {
+                return "01";
             }
-            return null;
+
+            final boolean sortFirst = name.startsWith("\001");
+
+            name = PATTERN_TRIM_BEFORE.matcher(name).replaceAll("");
+            if (TextUtils.isEmpty(name)) return null;
+
+            final Collator c = Collator.getInstance(Locale.ROOT);
+            c.setStrength(Collator.PRIMARY);
+            name = HexEncoding.encodeToString(c.getCollationKey(name).toByteArray(), false);
+
+            name = PATTERN_TRIM_AFTER.matcher(name).replaceAll("");
+            if (sortFirst) {
+                name = "01" + name;
+            }
+            return name;
         }
 
         public static final class Media implements AudioColumns {
@@ -2632,7 +2663,17 @@
             /**
              * A non human readable key calculated from the ARTIST, used for
              * searching, sorting and grouping
+             *
+             * @see Audio#keyFor(String)
+             * @deprecated These keys are generated using
+             *             {@link java.util.Locale#ROOT}, which means they don't
+             *             reflect locale-specific sorting preferences. To apply
+             *             locale-specific sorting preferences, use
+             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
+             *             {@code COLLATE LOCALIZED}, or
+             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
              */
+            @Deprecated
             @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
             public static final String ARTIST_KEY = "artist_key";
 
@@ -2736,6 +2777,23 @@
             public static final String ARTIST = "artist";
 
             /**
+             * A non human readable key calculated from the ARTIST, used for
+             * searching, sorting and grouping
+             *
+             * @see Audio#keyFor(String)
+             * @deprecated These keys are generated using
+             *             {@link java.util.Locale#ROOT}, which means they don't
+             *             reflect locale-specific sorting preferences. To apply
+             *             locale-specific sorting preferences, use
+             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
+             *             {@code COLLATE LOCALIZED}, or
+             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
+             */
+            @Deprecated
+            @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+            public static final String ARTIST_KEY = "artist_key";
+
+            /**
              * The number of songs on this album
              */
             @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
@@ -2770,7 +2828,17 @@
             /**
              * A non human readable key calculated from the ALBUM, used for
              * searching, sorting and grouping
+             *
+             * @see Audio#keyFor(String)
+             * @deprecated These keys are generated using
+             *             {@link java.util.Locale#ROOT}, which means they don't
+             *             reflect locale-specific sorting preferences. To apply
+             *             locale-specific sorting preferences, use
+             *             {@link ContentResolver#QUERY_ARG_SQL_SORT_ORDER} with
+             *             {@code COLLATE LOCALIZED}, or
+             *             {@link ContentResolver#QUERY_ARG_SORT_LOCALE}.
              */
+            @Deprecated
             @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
             public static final String ALBUM_KEY = "album_key";
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 457dcc0..800c15c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8241,20 +8241,6 @@
         public static final String AWARE_LOCK_ENABLED = "aware_lock_enabled";
 
         /**
-         * The settings values which should only be restored if the target device is the
-         * same as the source device
-         *
-         * NOTE: Settings are backed up and restored in the order they appear
-         *       in this array. If you have one setting depending on another,
-         *       make sure that they are ordered appropriately.
-         *
-         * @hide
-         */
-        public static final String[] DEVICE_SPECIFIC_SETTINGS_TO_BACKUP = {
-                DISPLAY_DENSITY_FORCED,
-        };
-
-        /**
          * Keys we no longer back up under the current schema, but want to continue to
          * process when restoring historical backup datasets.
          *
@@ -10877,16 +10863,13 @@
          * App standby (app idle) specific settings.
          * This is encoded as a key=value list, separated by commas. Ex:
          * <p>
-         * "idle_duration=5000,parole_interval=4500,screen_thresholds=0/0/60000/120000"
+         * "idle_duration=5000,prediction_timeout=4500,screen_thresholds=0/0/60000/120000"
          * <p>
          * All durations are in millis.
          * Array values are separated by forward slashes
          * The following keys are supported:
          *
          * <pre>
-         * parole_interval                  (long)
-         * parole_window                    (long)
-         * parole_duration                  (long)
          * screen_thresholds                (long[4])
          * elapsed_thresholds               (long[4])
          * strong_usage_duration            (long)
@@ -10897,17 +10880,12 @@
          * exempted_sync_duration           (long)
          * system_interaction_duration      (long)
          * initial_foreground_service_start_duration (long)
-         * stable_charging_threshold        (long)
-         *
-         * idle_duration        (long) // This is deprecated and used to circumvent b/26355386.
-         * idle_duration2       (long) // deprecated
-         * wallclock_threshold  (long) // deprecated
          * </pre>
          *
          * <p>
          * Type: string
          * @hide
-         * @see com.android.server.usage.UsageStatsService.SettingsObserver
+         * @see com.android.server.usage.AppStandbyController
          */
         public static final String APP_IDLE_CONSTANTS = "app_idle_constants";
 
diff --git a/core/java/android/service/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java
index 9184d6d..eefc1b7 100644
--- a/core/java/android/service/carrier/CarrierService.java
+++ b/core/java/android/service/carrier/CarrierService.java
@@ -22,7 +22,7 @@
 import android.os.IBinder;
 import android.os.PersistableBundle;
 import android.os.ResultReceiver;
-import android.os.telephony.TelephonyRegistryManager;
+import android.telephony.TelephonyRegistryManager;
 import android.util.Log;
 
 /**
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index f1c870d..dd2586c 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -126,11 +126,29 @@
             = "android.service.quicksettings.ACTIVE_TILE";
 
     /**
+     * Meta-data for a tile to support {@code BooleanState}.
+     * <p>
+     * BooleanState is for tiles that should support switch tile behavior in accessibility. This is
+     * the behavior of most of the framework tiles.
+     *
+     * To make a TileService support BooleanState, set this meta-data to true on the TileService's
+     * manifest declaration.
+     * <pre class="prettyprint">
+     * {@literal
+     * <meta-data android:name="android.service.quicksettings.BOOLEAN_TILE"
+     *      android:value="true" />
+     * }
+     * </pre>
+     */
+    public static final String META_DATA_BOOLEAN_TILE =
+            "android.service.quicksettings.BOOLEAN_TILE";
+
+    /**
      * Used to notify SysUI that Listening has be requested.
      * @hide
      */
-    public static final String ACTION_REQUEST_LISTENING
-            = "android.service.quicksettings.action.REQUEST_LISTENING";
+    public static final String ACTION_REQUEST_LISTENING =
+            "android.service.quicksettings.action.REQUEST_LISTENING";
 
     /**
      * @hide
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
similarity index 99%
rename from telephony/java/android/telephony/PhoneStateListener.java
rename to core/java/android/telephony/PhoneStateListener.java
index 1ba0a41..a65c8fd 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -35,8 +35,8 @@
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.IPhoneStateListener;
+import com.android.internal.annotations.VisibleForTesting;
 
 import dalvik.system.VMRuntime;
 
diff --git a/core/java/android/os/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
similarity index 75%
rename from core/java/android/os/telephony/TelephonyRegistryManager.java
rename to core/java/android/telephony/TelephonyRegistryManager.java
index 1332331..64d6124 100644
--- a/core/java/android/os/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -13,12 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.os.telephony;
+package android.telephony;
 
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.content.Context;
 import android.net.LinkProperties;
 import android.net.NetworkCapabilities;
+import android.os.Binder;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.Annotation.ApnType;
@@ -40,8 +46,15 @@
 import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting;
 import android.telephony.ims.ImsReasonInfo;
+import android.util.Log;
+
 import com.android.internal.telephony.ITelephonyRegistry;
+import com.android.internal.telephony.IOnSubscriptionsChangedListener;
+
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
 
 /**
  * A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update
@@ -58,9 +71,26 @@
 
     private static final String TAG = "TelephonyRegistryManager";
     private static ITelephonyRegistry sRegistry;
+    private final Context mContext;
+
+    /**
+     * A mapping between {@link SubscriptionManager.OnSubscriptionsChangedListener} and
+     * its callback IOnSubscriptionsChangedListener.
+     */
+    private final Map<SubscriptionManager.OnSubscriptionsChangedListener,
+                IOnSubscriptionsChangedListener> mSubscriptionChangedListenerMap = new HashMap<>();
+    /**
+     * A mapping between {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} and
+     * its callback IOnSubscriptionsChangedListener.
+     */
+    private final Map<SubscriptionManager.OnOpportunisticSubscriptionsChangedListener,
+            IOnSubscriptionsChangedListener> mOpportunisticSubscriptionChangedListenerMap
+            = new HashMap<>();
+
 
     /** @hide **/
-    public TelephonyRegistryManager() {
+    public TelephonyRegistryManager(@NonNull Context context) {
+        mContext = context;
         if (sRegistry == null) {
             sRegistry = ITelephonyRegistry.Stub.asInterface(
                 ServiceManager.getService("telephony.registry"));
@@ -68,6 +98,113 @@
     }
 
     /**
+     * Register for changes to the list of active {@link SubscriptionInfo} records or to the
+     * individual records themselves. When a change occurs the onSubscriptionsChanged method of
+     * the listener will be invoked immediately if there has been a notification. The
+     * onSubscriptionChanged method will also be triggered once initially when calling this
+     * function.
+     *
+     * @param listener an instance of {@link SubscriptionManager.OnSubscriptionsChangedListener}
+     *                 with onSubscriptionsChanged overridden.
+     * @param executor the executor that will execute callbacks.
+     */
+    public void addOnSubscriptionsChangedListener(
+            @NonNull SubscriptionManager.OnSubscriptionsChangedListener listener,
+            @NonNull Executor executor) {
+        IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
+            @Override
+            public void onSubscriptionsChanged () {
+                Log.d(TAG, "onSubscriptionsChangedListener callback received.");
+                executor.execute(() -> listener.onSubscriptionsChanged());
+            }
+        };
+        mSubscriptionChangedListenerMap.put(listener, callback);
+        try {
+            sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(), callback);
+        } catch (RemoteException ex) {
+            // system server crash
+        }
+    }
+
+    /**
+     * Unregister the {@link SubscriptionManager.OnSubscriptionsChangedListener}. This is not
+     * strictly necessary as the listener will automatically be unregistered if an attempt to
+     * invoke the listener fails.
+     *
+     * @param listener that is to be unregistered.
+     */
+    public void removeOnSubscriptionsChangedListener(
+            @NonNull SubscriptionManager.OnSubscriptionsChangedListener listener) {
+        if (mSubscriptionChangedListenerMap.get(listener) == null) {
+            return;
+        }
+        try {
+            sRegistry.removeOnSubscriptionsChangedListener(mContext.getOpPackageName(),
+                    mSubscriptionChangedListenerMap.get(listener));
+            mSubscriptionChangedListenerMap.remove(listener);
+        } catch (RemoteException ex) {
+            // system server crash
+        }
+    }
+
+    /**
+     * Register for changes to the list of opportunistic subscription records or to the
+     * individual records themselves. When a change occurs the onOpportunisticSubscriptionsChanged
+     * method of the listener will be invoked immediately if there has been a notification.
+     *
+     * @param listener an instance of
+     * {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} with
+     *                 onOpportunisticSubscriptionsChanged overridden.
+     * @param executor an Executor that will execute callbacks.
+     */
+    public void addOnOpportunisticSubscriptionsChangedListener(
+            @NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener,
+            @NonNull Executor executor) {
+        /**
+         * The callback methods need to be called on the executor thread where
+         * this object was created.  If the binder did that for us it'd be nice.
+         */
+        IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
+            @Override
+            public void onSubscriptionsChanged() {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    Log.d(TAG, "onOpportunisticSubscriptionsChanged callback received.");
+                    executor.execute(() -> listener.onOpportunisticSubscriptionsChanged());
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+        };
+        mOpportunisticSubscriptionChangedListenerMap.put(listener, callback);
+        try {
+            sRegistry.addOnOpportunisticSubscriptionsChangedListener(mContext.getOpPackageName(),
+                    callback);
+        } catch (RemoteException ex) {
+            // system server crash
+        }
+    }
+
+    /**
+     * Unregister the {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener}
+     * that is currently listening opportunistic subscriptions change. This is not strictly
+     * necessary as the listener will automatically be unregistered if an attempt to invoke the
+     * listener fails.
+     *
+     * @param listener that is to be unregistered.
+     */
+    public void removeOnOpportunisticSubscriptionsChangedListener(
+            @NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener) {
+        try {
+            sRegistry.removeOnSubscriptionsChangedListener(mContext.getOpPackageName(),
+                    mOpportunisticSubscriptionChangedListenerMap.get(listener));
+            mOpportunisticSubscriptionChangedListenerMap.remove(listener);
+        } catch (RemoteException ex) {
+            // system server crash
+        }
+    }
+
+    /**
      * Informs the system of an intentional upcoming carrier network change by a carrier app.
      * This call only used to allow the system to provide alternative UI while telephony is
      * performing an action that may result in intentional, temporary network lack of connectivity.
@@ -546,4 +683,15 @@
         }
     }
 
+    /**
+     * @param activeDataSubId
+     * @hide
+     */
+    public void notifyActiveDataSubIdChanged(int activeDataSubId) {
+        try {
+            sRegistry.notifyActiveDataSubIdChanged(activeDataSubId);
+        } catch (RemoteException ex) {
+
+        }
+    }
 }
diff --git a/core/java/android/util/DebugUtils.java b/core/java/android/util/DebugUtils.java
index 20e0d14..bc5edf8 100644
--- a/core/java/android/util/DebugUtils.java
+++ b/core/java/android/util/DebugUtils.java
@@ -255,7 +255,7 @@
                     if (value == 0 && flagsWasZero) {
                         return constNameWithoutPrefix(prefix, field);
                     }
-                    if ((flags & value) == value) {
+                    if (value != 0 && (flags & value) == value) {
                         flags &= ~value;
                         res.append(constNameWithoutPrefix(prefix, field)).append('|');
                     }
diff --git a/core/java/android/util/LongSparseArray.java b/core/java/android/util/LongSparseArray.java
index d3b2c46..e78b796 100644
--- a/core/java/android/util/LongSparseArray.java
+++ b/core/java/android/util/LongSparseArray.java
@@ -16,8 +16,12 @@
 
 package android.util;
 
+import android.os.Parcel;
+import android.os.Parcelable;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
+import com.android.internal.util.Preconditions;
 
 import libcore.util.EmptyArray;
 
@@ -442,4 +446,93 @@
         buffer.append('}');
         return buffer.toString();
     }
+
+    /**
+     * @hide
+     */
+    public static class StringParcelling implements com.android.internal.util.Parcelling {
+        @Override
+        public void parcel(Object item, Parcel dest, int parcelFlags) {
+            if (item == null) {
+                dest.writeInt(-1);
+                return;
+            }
+
+            LongSparseArray<String> array = (LongSparseArray<String>) item;
+            dest.writeInt(array.mSize);
+            dest.writeLongArray(array.mKeys);
+            dest.writeStringArray((String[]) array.mValues);
+        }
+
+        @Override
+        public Object unparcel(Parcel source) {
+            int size = source.readInt();
+            if (size == -1) {
+                return null;
+            }
+
+            LongSparseArray<String> array = new LongSparseArray<>(0);
+            array.mSize = size;
+            array.mKeys = source.createLongArray();
+            array.mValues = source.createStringArray();
+
+            // Make sure array is sane
+            Preconditions.checkArgument(array.mKeys.length >= size);
+            Preconditions.checkArgument(array.mValues.length >= size);
+
+            if (size > 0) {
+                long last = array.mKeys[0];
+                for (int i = 1; i < size; i++) {
+                    Preconditions.checkArgument(last < array.mKeys[i]);
+                }
+            }
+
+            return array;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public static class Parcelling<T extends Parcelable> implements
+            com.android.internal.util.Parcelling {
+        @Override
+        public void parcel(Object item, Parcel dest, int parcelFlags) {
+            if (item == null) {
+                dest.writeInt(-1);
+                return;
+            }
+
+            LongSparseArray<T> array = (LongSparseArray<T>) item;
+            dest.writeInt(array.mSize);
+            dest.writeLongArray(array.mKeys);
+            dest.writeParcelableArray((T[]) array.mValues, parcelFlags);
+        }
+
+        @Override
+        public Object unparcel(Parcel source) {
+            int size = source.readInt();
+            if (size == -1) {
+                return null;
+            }
+
+            LongSparseArray<T> array = new LongSparseArray<>(0);
+            array.mSize = size;
+            array.mKeys = source.createLongArray();
+            array.mValues = source.readParcelableArray(null);
+
+            // Make sure array is sane
+            Preconditions.checkArgument(array.mKeys.length >= size);
+            Preconditions.checkArgument(array.mValues.length >= size);
+
+            if (size > 0) {
+                long last = array.mKeys[0];
+                for (int i = 1; i < size; i++) {
+                    Preconditions.checkArgument(last < array.mKeys[i]);
+                }
+            }
+
+            return array;
+        }
+    }
 }
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index 7b7eea0..9ffd4f0 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -17,9 +17,11 @@
 package android.util;
 
 import android.annotation.UnsupportedAppUsage;
+import android.os.Parcel;
 
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
+import com.android.internal.util.Preconditions;
 
 import libcore.util.EmptyArray;
 
@@ -283,4 +285,49 @@
         buffer.append('}');
         return buffer.toString();
     }
+
+    /**
+     * @hide
+     */
+    public static class Parcelling implements com.android.internal.util.Parcelling {
+        @Override
+        public void parcel(Object item, Parcel dest, int parcelFlags) {
+            if (item == null) {
+                dest.writeInt(-1);
+                return;
+            }
+
+            LongSparseLongArray array = (LongSparseLongArray) item;
+            dest.writeInt(array.mSize);
+            dest.writeLongArray(array.mKeys);
+            dest.writeLongArray(array.mValues);
+        }
+
+        @Override
+        public Object unparcel(Parcel source) {
+            int size = source.readInt();
+            if (size == -1) {
+                return null;
+            }
+
+            LongSparseLongArray array = new LongSparseLongArray(0);
+
+            array.mSize = size;
+            array.mKeys = source.createLongArray();
+            array.mValues = source.createLongArray();
+
+            // Make sure array is sane
+            Preconditions.checkArgument(array.mKeys.length >= size);
+            Preconditions.checkArgument(array.mValues.length >= size);
+
+            if (size > 0) {
+                long last = array.mKeys[0];
+                for (int i = 1; i < size; i++) {
+                    Preconditions.checkArgument(last < array.mKeys[i]);
+                }
+            }
+
+            return array;
+        }
+    }
 }
diff --git a/core/java/android/util/TimestampedValue.java b/core/java/android/util/TimestampedValue.java
index 1289e4d..4505673 100644
--- a/core/java/android/util/TimestampedValue.java
+++ b/core/java/android/util/TimestampedValue.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.SystemClock;
 
 import java.util.Objects;
@@ -30,14 +31,14 @@
  * If a suitable clock is used the reference time can be used to identify the age of a value or
  * ordering between values.
  *
- * <p>To read and write a timestamped value from / to a Parcel see
- * {@link #readFromParcel(Parcel, ClassLoader, Class)} and
- * {@link #writeToParcel(Parcel, TimestampedValue)}.
+ * <p>This class implements {@link Parcelable} for convenience but instances will only actually be
+ * parcelable if the value type held is {@code null}, {@link Parcelable}, or one of the other types
+ * supported by {@link Parcel#writeValue(Object)} / {@link Parcel#readValue(ClassLoader)}.
  *
  * @param <T> the type of the value with an associated timestamp
  * @hide
  */
-public final class TimestampedValue<T> {
+public final class TimestampedValue<T> implements Parcelable {
     private final long mReferenceTimeMillis;
     private final T mValue;
 
@@ -81,57 +82,43 @@
     }
 
     /**
-     * Read a {@link TimestampedValue} from a parcel that was stored using
-     * {@link #writeToParcel(Parcel, TimestampedValue)}.
-     *
-     * <p>The marshalling/unmarshalling of the value relies upon {@link Parcel#writeValue(Object)}
-     * and {@link Parcel#readValue(ClassLoader)} and so this method can only be used with types
-     * supported by those methods.
-     *
-     * @param in the Parcel to read from
-     * @param classLoader the ClassLoader to pass to {@link Parcel#readValue(ClassLoader)}
-     * @param valueClass the expected type of the value, typically the same as {@code <T>} but can
-     *     also be a subclass
-     * @throws RuntimeException if the value read is not compatible with {@code valueClass} or the
-     *     object could not be read
-     */
-    @SuppressWarnings("unchecked")
-    @NonNull
-    public static <T> TimestampedValue<T> readFromParcel(
-            @NonNull Parcel in, @Nullable ClassLoader classLoader, Class<? extends T> valueClass) {
-        long referenceTimeMillis = in.readLong();
-        T value = (T) in.readValue(classLoader);
-        // Equivalent to static code: if (!(value.getClass() instanceof {valueClass})) {
-        if (value != null && !valueClass.isAssignableFrom(value.getClass())) {
-            throw new RuntimeException("Value was of type " + value.getClass()
-                    + " is not assignable to " + valueClass);
-        }
-        return new TimestampedValue<>(referenceTimeMillis, value);
-    }
-
-    /**
-     * Write a {@link TimestampedValue} to a parcel so that it can be read using
-     * {@link #readFromParcel(Parcel, ClassLoader, Class)}.
-     *
-     * <p>The marshalling/unmarshalling of the value relies upon {@link Parcel#writeValue(Object)}
-     * and {@link Parcel#readValue(ClassLoader)} and so this method can only be used with types
-     * supported by those methods.
-     *
-     * @param dest the Parcel
-     * @param timestampedValue the value
-     * @throws RuntimeException if the value could not be written to the Parcel
-     */
-    public static void writeToParcel(
-            @NonNull Parcel dest, @NonNull TimestampedValue<?> timestampedValue) {
-        dest.writeLong(timestampedValue.mReferenceTimeMillis);
-        dest.writeValue(timestampedValue.mValue);
-    }
-
-    /**
      * Returns the difference in milliseconds between two instance's reference times.
      */
     public static long referenceTimeDifference(
             @NonNull TimestampedValue<?> one, @NonNull TimestampedValue<?> two) {
         return one.mReferenceTimeMillis - two.mReferenceTimeMillis;
     }
+
+    public static final @NonNull Parcelable.Creator<TimestampedValue<?>> CREATOR =
+            new Parcelable.ClassLoaderCreator<TimestampedValue<?>>() {
+
+                @Override
+                public TimestampedValue<?> createFromParcel(@NonNull Parcel source) {
+                    return createFromParcel(source, null);
+                }
+
+                @Override
+                public TimestampedValue<?> createFromParcel(
+                        @NonNull Parcel source, @Nullable ClassLoader classLoader) {
+                    long referenceTimeMillis = source.readLong();
+                    Object value = source.readValue(classLoader);
+                    return new TimestampedValue<>(referenceTimeMillis, value);
+                }
+
+                @Override
+                public TimestampedValue[] newArray(int size) {
+                    return new TimestampedValue[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeLong(mReferenceTimeMillis);
+        dest.writeValue(mValue);
+    }
 }
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index 955be8d..762366e 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -120,4 +120,10 @@
      * @see IRecentsAnimationRunner#onCancelled
      */
     void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot);
+
+    /**
+     * Sets a state for controller to decide which surface is the destination when the recents
+     * animation is cancelled through fail safe mechanism.
+     */
+    void setWillFinishToHome(boolean willFinishToHome);
 }
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 4b872d3..8bf99ec 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -81,6 +81,14 @@
      */
     void showInsets(int types, boolean fromIme);
 
+    /**
+     * Called when a set of insets source window should be hidden by policy.
+     *
+     * @param types internal inset types (WindowInsets.Type.InsetType) to hide
+     * @param fromIme true if this request originated from IME (InputMethodService).
+     */
+    void hideInsets(int types, boolean fromIme);
+
     void moved(int newX, int newY);
     void dispatchAppVisibility(boolean visible);
     void dispatchGetNewSurface();
diff --git a/core/java/android/view/InputMonitor.java b/core/java/android/view/InputMonitor.java
index 1a1d7e6..ad1f201 100644
--- a/core/java/android/view/InputMonitor.java
+++ b/core/java/android/view/InputMonitor.java
@@ -40,8 +40,6 @@
     private static final boolean DEBUG = false;
 
     @NonNull
-    private final String mName;
-    @NonNull
     private final InputChannel mInputChannel;
     @NonNull
     private final IInputMonitorHost mHost;
@@ -81,23 +79,19 @@
 
 
 
-    // Code below generated by codegen v1.0.1.
+    // Code below generated by codegen v1.0.7.
     //
     // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
     // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/InputMonitor.java
-    //
-    // CHECKSTYLE:OFF Generated code
+
 
     @DataClass.Generated.Member
     public InputMonitor(
-            @NonNull String name,
             @NonNull InputChannel inputChannel,
             @NonNull IInputMonitorHost host) {
-        this.mName = name;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mName);
         this.mInputChannel = inputChannel;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mInputChannel);
@@ -109,11 +103,6 @@
     }
 
     @DataClass.Generated.Member
-    public @NonNull String getName() {
-        return mName;
-    }
-
-    @DataClass.Generated.Member
     public @NonNull InputChannel getInputChannel() {
         return mInputChannel;
     }
@@ -130,7 +119,6 @@
         // String fieldNameToString() { ... }
 
         return "InputMonitor { " +
-                "name = " + mName + ", " +
                 "inputChannel = " + mInputChannel + ", " +
                 "host = " + mHost +
         " }";
@@ -142,7 +130,6 @@
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
-        dest.writeString(mName);
         dest.writeTypedObject(mInputChannel, flags);
         dest.writeStrongInterface(mHost);
     }
@@ -151,6 +138,26 @@
     @DataClass.Generated.Member
     public int describeContents() { return 0; }
 
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ InputMonitor(Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        InputChannel inputChannel = (InputChannel) in.readTypedObject(InputChannel.CREATOR);
+        IInputMonitorHost host = IInputMonitorHost.Stub.asInterface(in.readStrongBinder());
+
+        this.mInputChannel = inputChannel;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mInputChannel);
+        this.mHost = host;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mHost);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
     @DataClass.Generated.Member
     public static final @NonNull Parcelable.Creator<InputMonitor> CREATOR
             = new Parcelable.Creator<InputMonitor>() {
@@ -160,26 +167,16 @@
         }
 
         @Override
-        @SuppressWarnings({"unchecked", "RedundantCast"})
         public InputMonitor createFromParcel(Parcel in) {
-            // You can override field unparcelling by defining methods like:
-            // static FieldType unparcelFieldName(Parcel in) { ... }
-
-            String name = in.readString();
-            InputChannel inputChannel = (InputChannel) in.readTypedObject(InputChannel.CREATOR);
-            IInputMonitorHost host = IInputMonitorHost.Stub.asInterface(in.readStrongBinder());
-            return new InputMonitor(
-                    name,
-                    inputChannel,
-                    host);
+            return new InputMonitor(in);
         }
     };
 
     @DataClass.Generated(
-            time = 1569871940995L,
-            codegenVersion = "1.0.1",
+            time = 1571177265149L,
+            codegenVersion = "1.0.7",
             sourceFile = "frameworks/base/core/java/android/view/InputMonitor.java",
-            inputSignatures = "private static final  java.lang.String TAG\nprivate static final  boolean DEBUG\nprivate final @android.annotation.NonNull java.lang.String mName\nprivate final @android.annotation.NonNull android.view.InputChannel mInputChannel\nprivate final @android.annotation.NonNull android.view.IInputMonitorHost mHost\npublic  void pilferPointers()\npublic  void dispose()\nclass InputMonitor extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true)")
+            inputSignatures = "private static final  java.lang.String TAG\nprivate static final  boolean DEBUG\nprivate final @android.annotation.NonNull android.view.InputChannel mInputChannel\nprivate final @android.annotation.NonNull android.view.IInputMonitorHost mHost\npublic  void pilferPointers()\npublic  void dispose()\nclass InputMonitor extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 341c214..e4deffa 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -229,6 +229,10 @@
             final InsetsSourceConsumer consumer = items.valueAt(i);
             final InsetsSource source = mInitialInsetsState.getSource(consumer.getType());
             final InsetsSourceControl control = consumer.getControl();
+            if (control == null) {
+                // Control may not be available for consumer yet or revoked.
+                continue;
+            }
             final SurfaceControl leash = consumer.getControl().getLeash();
 
             mTmpMatrix.setTranslate(control.getSurfacePosition().x, control.getSurfacePosition().y);
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 5a8636d..5bb4f63 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -251,6 +251,10 @@
 
     @Override
     public void hide(@InsetType int types) {
+        hide(types, false /* fromIme */);
+    }
+
+    void hide(@InsetType int types, boolean fromIme) {
         int typesReady = 0;
         final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
         for (int i = internalTypes.size() - 1; i >= 0; i--) {
@@ -265,7 +269,7 @@
             }
             typesReady |= InsetsState.toPublicType(consumer.getType());
         }
-        applyAnimation(typesReady, false /* show */, false /* fromIme */);
+        applyAnimation(typesReady, false /* show */, fromIme /* fromIme */);
     }
 
     @Override
@@ -331,42 +335,35 @@
         boolean isReady = true;
         for (int i = internalTypes.size() - 1; i >= 0; i--) {
             InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i));
-            // Double check for IME that IME target window has focus.
-            if (consumer.getType() != TYPE_IME || consumer.hasWindowFocus()) {
-                boolean setVisible = !consumer.isVisible();
-                if (setVisible) {
-                    // Show request
-                    switch(consumer.requestShow(fromIme)) {
-                        case ShowResult.SHOW_IMMEDIATELY:
-                            typesReady |= InsetsState.toPublicType(consumer.getType());
-                            break;
-                        case ShowResult.SHOW_DELAYED:
-                            isReady = false;
-                            break;
-                        case ShowResult.SHOW_FAILED:
-                            // IME cannot be shown (since it didn't have focus), proceed
-                            // with animation of other types.
-                            if (mPendingTypesToShow != 0) {
-                                // remove IME from pending because view no longer has focus.
-                                mPendingTypesToShow &= ~InsetsState.toPublicType(TYPE_IME);
-                            }
-                            break;
-                    }
-                } else {
-                    // Hide request
-                    // TODO: Move notifyHidden() to beginning of the hide animation
-                    // (when visibility actually changes using hideDirectly()).
-                    consumer.notifyHidden();
-                    typesReady |= InsetsState.toPublicType(consumer.getType());
+            boolean setVisible = !consumer.isVisible();
+            if (setVisible) {
+                // Show request
+                switch(consumer.requestShow(fromIme)) {
+                    case ShowResult.SHOW_IMMEDIATELY:
+                        typesReady |= InsetsState.toPublicType(consumer.getType());
+                        break;
+                    case ShowResult.SHOW_DELAYED:
+                        isReady = false;
+                        break;
+                    case ShowResult.SHOW_FAILED:
+                        // IME cannot be shown (since it didn't have focus), proceed
+                        // with animation of other types.
+                        if (mPendingTypesToShow != 0) {
+                            // remove IME from pending because view no longer has focus.
+                            mPendingTypesToShow &= ~InsetsState.toPublicType(TYPE_IME);
+                        }
+                        break;
                 }
-                consumers.put(consumer.getType(), consumer);
             } else {
-                // window doesnt have focus, no-op.
-                isReady = false;
-                // TODO: Let the calling app know that window has lost focus and
-                //       show()/hide()/controlWindowInsetsAnimation requests will be ignored.
-                typesReady &= ~InsetsState.toPublicType(consumer.getType());
+                // Hide request
+                // TODO: Move notifyHidden() to beginning of the hide animation
+                // (when visibility actually changes using hideDirectly()).
+                if (!fromIme) {
+                    consumer.notifyHidden();
+                }
+                typesReady |= InsetsState.toPublicType(consumer.getType());
             }
+            consumers.put(consumer.getType(), consumer);
         }
         return new Pair<>(typesReady, isReady);
     }
diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java
index 2fd2e96..c5d45c3 100644
--- a/core/java/android/view/SurfaceHolder.java
+++ b/core/java/android/view/SurfaceHolder.java
@@ -16,7 +16,10 @@
 
 package android.view;
 
+import android.annotation.IntRange;
+import android.annotation.NonNull;
 import android.graphics.Canvas;
+import android.graphics.PixelFormat;
 import android.graphics.Rect;
 
 /**
@@ -76,7 +79,7 @@
          *
          * @param holder The SurfaceHolder whose surface is being created.
          */
-        public void surfaceCreated(SurfaceHolder holder);
+        void surfaceCreated(@NonNull SurfaceHolder holder);
 
         /**
          * This is called immediately after any structural changes (format or
@@ -85,12 +88,12 @@
          * once, after {@link #surfaceCreated}.
          *
          * @param holder The SurfaceHolder whose surface has changed.
-         * @param format The new PixelFormat of the surface.
+         * @param format The new {@link PixelFormat} of the surface.
          * @param width The new width of the surface.
          * @param height The new height of the surface.
          */
-        public void surfaceChanged(SurfaceHolder holder, int format, int width,
-                int height);
+        void surfaceChanged(@NonNull SurfaceHolder holder, @PixelFormat.Format int format,
+                @IntRange(from = 0) int width, @IntRange(from = 0) int height);
 
         /**
          * This is called immediately before a surface is being destroyed. After
@@ -101,7 +104,7 @@
          *
          * @param holder The SurfaceHolder whose surface is being destroyed.
          */
-        public void surfaceDestroyed(SurfaceHolder holder);
+        void surfaceDestroyed(@NonNull SurfaceHolder holder);
     }
 
     /**
@@ -122,7 +125,7 @@
          *
          * @param holder The SurfaceHolder whose surface has changed.
          */
-        void surfaceRedrawNeeded(SurfaceHolder holder);
+        void surfaceRedrawNeeded(@NonNull SurfaceHolder holder);
 
         /**
          * An alternative to surfaceRedrawNeeded where it is not required to block
@@ -140,7 +143,8 @@
          * from any thread.
          *
          */
-        default void surfaceRedrawNeededAsync(SurfaceHolder holder, Runnable drawingFinished) {
+        default void surfaceRedrawNeededAsync(@NonNull SurfaceHolder holder,
+                @NonNull Runnable drawingFinished) {
             surfaceRedrawNeeded(holder);
             drawingFinished.run();
         }
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 8a1fd62..ad59ae5 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -32,6 +32,7 @@
 import android.os.Debug;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.Message;
 import android.os.RemoteException;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -46,6 +47,7 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
+import java.lang.annotation.Annotation;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -53,12 +55,12 @@
 import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.util.ArrayDeque;
-import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
@@ -68,6 +70,7 @@
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Function;
+import java.util.stream.Stream;
 
 /**
  * Various debugging/tracing tools related to {@link View} and the view hierarchy.
@@ -331,11 +334,83 @@
         public View findHierarchyView(String className, int hashCode);
     }
 
-    private static HashMap<Class<?>, Method[]> mCapturedViewMethodsForClasses = null;
-    private static HashMap<Class<?>, Field[]> mCapturedViewFieldsForClasses = null;
+    private abstract static class PropertyInfo<T extends Annotation,
+            R extends AccessibleObject & Member> {
+
+        public final R member;
+        public final T property;
+        public final String name;
+        public final Class<?> returnType;
+
+        public String entrySuffix = "";
+        public String valueSuffix = "";
+
+        PropertyInfo(Class<T> property, R member, Class<?> returnType) {
+            this.member = member;
+            this.name = member.getName();
+            this.property = member.getAnnotation(property);
+            this.returnType = returnType;
+        }
+
+        public abstract Object invoke(Object target) throws Exception;
+
+        static <T extends Annotation> PropertyInfo<T, ?> forMethod(Method method,
+                Class<T> property) {
+            // Ensure the method return and parameter types can be resolved.
+            try {
+                if ((method.getReturnType() == Void.class)
+                        || (method.getParameterTypes().length != 0)) {
+                    return null;
+                }
+            } catch (NoClassDefFoundError e) {
+                return null;
+            }
+            if (!method.isAnnotationPresent(property)) {
+                return null;
+            }
+            method.setAccessible(true);
+
+            PropertyInfo info = new MethodPI(method, property);
+            info.entrySuffix = "()";
+            info.valueSuffix = ";";
+            return info;
+        }
+
+        static <T extends Annotation> PropertyInfo<T, ?> forField(Field field, Class<T> property) {
+            if (!field.isAnnotationPresent(property)) {
+                return null;
+            }
+            field.setAccessible(true);
+            return new FieldPI<>(field, property);
+        }
+    }
+
+    private static class MethodPI<T extends Annotation> extends PropertyInfo<T, Method> {
+
+        MethodPI(Method method, Class<T> property) {
+            super(property, method, method.getReturnType());
+        }
+
+        @Override
+        public Object invoke(Object target) throws Exception {
+            return member.invoke(target);
+        }
+    }
+
+    private static class FieldPI<T extends Annotation> extends PropertyInfo<T, Field> {
+
+        FieldPI(Field field, Class<T> property) {
+            super(property, field, field.getType());
+        }
+
+        @Override
+        public Object invoke(Object target) throws Exception {
+            return member.get(target);
+        }
+    }
 
     // Maximum delay in ms after which we stop trying to capture a View's drawing
-    private static final int CAPTURE_TIMEOUT = 4000;
+    private static final int CAPTURE_TIMEOUT = 6000;
 
     private static final String REMOTE_COMMAND_CAPTURE = "CAPTURE";
     private static final String REMOTE_COMMAND_DUMP = "DUMP";
@@ -346,9 +421,9 @@
     private static final String REMOTE_COMMAND_CAPTURE_LAYERS = "CAPTURE_LAYERS";
     private static final String REMOTE_COMMAND_OUTPUT_DISPLAYLIST = "OUTPUT_DISPLAYLIST";
 
-    private static HashMap<Class<?>, Field[]> sFieldsForClasses;
-    private static HashMap<Class<?>, Method[]> sMethodsForClasses;
-    private static HashMap<AccessibleObject, ExportedProperty> sAnnotations;
+    private static HashMap<Class<?>, PropertyInfo<ExportedProperty, ?>[]> sExportProperties;
+    private static HashMap<Class<?>, PropertyInfo<CapturedViewProperty, ?>[]>
+            sCapturedViewProperties;
 
     /**
      * @deprecated This enum is now unused
@@ -1157,6 +1232,69 @@
 
     private static void dumpViewHierarchy(Context context, ViewGroup group,
             BufferedWriter out, int level, boolean skipChildren, boolean includeProperties) {
+        cacheExportedProperties(group.getClass());
+        if (!skipChildren) {
+            cacheExportedPropertiesForChildren(group);
+        }
+        // Try to use the handler provided by the view
+        Handler handler = group.getHandler();
+        // Fall back on using the main thread
+        if (handler == null) {
+            handler = new Handler(Looper.getMainLooper());
+        }
+
+        if (handler.getLooper() == Looper.myLooper()) {
+            dumpViewHierarchyOnUIThread(context, group, out, level, skipChildren,
+                    includeProperties);
+        } else {
+            FutureTask task = new FutureTask(() ->
+                    dumpViewHierarchyOnUIThread(context, group, out, level, skipChildren,
+                            includeProperties), null);
+            Message msg = Message.obtain(handler, task);
+            msg.setAsynchronous(true);
+            handler.sendMessage(msg);
+            while (true) {
+                try {
+                    task.get(CAPTURE_TIMEOUT, java.util.concurrent.TimeUnit.MILLISECONDS);
+                    return;
+                } catch (InterruptedException e) {
+                    // try again
+                } catch (ExecutionException | TimeoutException e) {
+                    // Something unexpected happened.
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+    }
+
+    private static void cacheExportedPropertiesForChildren(ViewGroup group) {
+        final int count = group.getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View view = group.getChildAt(i);
+            cacheExportedProperties(view.getClass());
+            if (view instanceof ViewGroup) {
+                cacheExportedPropertiesForChildren((ViewGroup) view);
+            }
+        }
+    }
+
+    private static void cacheExportedProperties(Class<?> klass) {
+        if (sExportProperties != null && sExportProperties.containsKey(klass)) {
+            return;
+        }
+        do {
+            for (PropertyInfo<ExportedProperty, ?> info : getExportedProperties(klass)) {
+                if (!info.returnType.isPrimitive() && info.property.deepExport()) {
+                    cacheExportedProperties(info.returnType);
+                }
+            }
+            klass = klass.getSuperclass();
+        } while (klass != Object.class);
+    }
+
+
+    private static void dumpViewHierarchyOnUIThread(Context context, ViewGroup group,
+            BufferedWriter out, int level, boolean skipChildren, boolean includeProperties) {
         if (!dumpView(context, group, out, level, includeProperties)) {
             return;
         }
@@ -1169,16 +1307,16 @@
         for (int i = 0; i < count; i++) {
             final View view = group.getChildAt(i);
             if (view instanceof ViewGroup) {
-                dumpViewHierarchy(context, (ViewGroup) view, out, level + 1, skipChildren,
-                        includeProperties);
+                dumpViewHierarchyOnUIThread(context, (ViewGroup) view, out, level + 1,
+                        skipChildren, includeProperties);
             } else {
                 dumpView(context, view, out, level + 1, includeProperties);
             }
             if (view.mOverlay != null) {
                 ViewOverlay overlay = view.getOverlay();
                 ViewGroup overlayContainer = overlay.mOverlayViewGroup;
-                dumpViewHierarchy(context, overlayContainer, out, level + 2, skipChildren,
-                        includeProperties);
+                dumpViewHierarchyOnUIThread(context, overlayContainer, out, level + 2,
+                        skipChildren, includeProperties);
             }
         }
         if (group instanceof HierarchyHandler) {
@@ -1212,81 +1350,28 @@
         return true;
     }
 
-    private static Field[] getExportedPropertyFields(Class<?> klass) {
-        if (sFieldsForClasses == null) {
-            sFieldsForClasses = new HashMap<Class<?>, Field[]>();
-        }
-        if (sAnnotations == null) {
-            sAnnotations = new HashMap<AccessibleObject, ExportedProperty>(512);
-        }
-
-        final HashMap<Class<?>, Field[]> map = sFieldsForClasses;
-
-        Field[] fields = map.get(klass);
-        if (fields != null) {
-            return fields;
-        }
-
-        try {
-            final Field[] declaredFields = klass.getDeclaredFieldsUnchecked(false);
-            final ArrayList<Field> foundFields = new ArrayList<Field>();
-            for (final Field field : declaredFields) {
-              // Fields which can't be resolved have a null type.
-              if (field.getType() != null && field.isAnnotationPresent(ExportedProperty.class)) {
-                  field.setAccessible(true);
-                  foundFields.add(field);
-                  sAnnotations.put(field, field.getAnnotation(ExportedProperty.class));
-              }
-            }
-            fields = foundFields.toArray(new Field[foundFields.size()]);
-            map.put(klass, fields);
-        } catch (NoClassDefFoundError e) {
-            throw new AssertionError(e);
-        }
-
-        return fields;
+    private static <T extends Annotation> PropertyInfo<T, ?>[] convertToPropertyInfos(
+            Method[] methods, Field[] fields, Class<T> property) {
+        return Stream.of(Arrays.stream(methods).map(m -> PropertyInfo.forMethod(m, property)),
+                Arrays.stream(fields).map(f -> PropertyInfo.forField(f, property)))
+                .flatMap(Function.identity())
+                .filter(i -> i != null)
+                .toArray(PropertyInfo[]::new);
     }
 
-    private static Method[] getExportedPropertyMethods(Class<?> klass) {
-        if (sMethodsForClasses == null) {
-            sMethodsForClasses = new HashMap<Class<?>, Method[]>(100);
+    private static PropertyInfo<ExportedProperty, ?>[] getExportedProperties(Class<?> klass) {
+        if (sExportProperties == null) {
+            sExportProperties = new HashMap<>();
         }
-        if (sAnnotations == null) {
-            sAnnotations = new HashMap<AccessibleObject, ExportedProperty>(512);
+        final HashMap<Class<?>, PropertyInfo<ExportedProperty, ?>[]> map = sExportProperties;
+        PropertyInfo<ExportedProperty, ?>[] properties = sExportProperties.get(klass);
+
+        if (properties == null) {
+            properties = convertToPropertyInfos(klass.getDeclaredMethodsUnchecked(false),
+                    klass.getDeclaredFieldsUnchecked(false), ExportedProperty.class);
+            map.put(klass, properties);
         }
-
-        final HashMap<Class<?>, Method[]> map = sMethodsForClasses;
-
-        Method[] methods = map.get(klass);
-        if (methods != null) {
-            return methods;
-        }
-
-        methods = klass.getDeclaredMethodsUnchecked(false);
-
-        final ArrayList<Method> foundMethods = new ArrayList<Method>();
-        for (final Method method : methods) {
-            // Ensure the method return and parameter types can be resolved.
-            try {
-                method.getReturnType();
-                method.getParameterTypes();
-            } catch (NoClassDefFoundError e) {
-                continue;
-            }
-
-            if (method.getParameterTypes().length == 0 &&
-                    method.isAnnotationPresent(ExportedProperty.class) &&
-                    method.getReturnType() != Void.class) {
-                method.setAccessible(true);
-                foundMethods.add(method);
-                sAnnotations.put(method, method.getAnnotation(ExportedProperty.class));
-            }
-        }
-
-        methods = foundMethods.toArray(new Method[foundMethods.size()]);
-        map.put(klass, methods);
-
-        return methods;
+        return properties;
     }
 
     private static void dumpViewProperties(Context context, Object view,
@@ -1305,233 +1390,97 @@
 
         Class<?> klass = view.getClass();
         do {
-            exportFields(context, view, out, klass, prefix);
-            exportMethods(context, view, out, klass, prefix);
+            writeExportedProperties(context, view, out, klass, prefix);
             klass = klass.getSuperclass();
         } while (klass != Object.class);
     }
 
-    private static Object callMethodOnAppropriateTheadBlocking(final Method method,
-            final Object object) throws IllegalAccessException, InvocationTargetException,
-            TimeoutException {
-        if (!(object instanceof View)) {
-            return method.invoke(object, (Object[]) null);
-        }
-
-        final View view = (View) object;
-        Callable<Object> callable = new Callable<Object>() {
-            @Override
-            public Object call() throws IllegalAccessException, InvocationTargetException {
-                return method.invoke(view, (Object[]) null);
-            }
-        };
-        FutureTask<Object> future = new FutureTask<Object>(callable);
-        // Try to use the handler provided by the view
-        Handler handler = view.getHandler();
-        // Fall back on using the main thread
-        if (handler == null) {
-            handler = new Handler(android.os.Looper.getMainLooper());
-        }
-        handler.post(future);
-        while (true) {
-            try {
-                return future.get(CAPTURE_TIMEOUT, java.util.concurrent.TimeUnit.MILLISECONDS);
-            } catch (ExecutionException e) {
-                Throwable t = e.getCause();
-                if (t instanceof IllegalAccessException) {
-                    throw (IllegalAccessException)t;
-                }
-                if (t instanceof InvocationTargetException) {
-                    throw (InvocationTargetException)t;
-                }
-                throw new RuntimeException("Unexpected exception", t);
-            } catch (InterruptedException e) {
-                // Call get again
-            } catch (CancellationException e) {
-                throw new RuntimeException("Unexpected cancellation exception", e);
-            }
-        }
-    }
-
     private static String formatIntToHexString(int value) {
         return "0x" + Integer.toHexString(value).toUpperCase();
     }
 
-    private static void exportMethods(Context context, Object view, BufferedWriter out,
+    private static void writeExportedProperties(Context context, Object view, BufferedWriter out,
             Class<?> klass, String prefix) throws IOException {
-
-        final Method[] methods = getExportedPropertyMethods(klass);
-        int count = methods.length;
-        for (int i = 0; i < count; i++) {
-            final Method method = methods[i];
+        for (PropertyInfo<ExportedProperty, ?> info : getExportedProperties(klass)) {
             //noinspection EmptyCatchBlock
+            Object value;
             try {
-                Object methodValue = callMethodOnAppropriateTheadBlocking(method, view);
-                final Class<?> returnType = method.getReturnType();
-                final ExportedProperty property = sAnnotations.get(method);
-                String categoryPrefix =
-                        property.category().length() != 0 ? property.category() + ":" : "";
-
-                if (returnType == int.class) {
-                    if (property.resolveId() && context != null) {
-                        final int id = (Integer) methodValue;
-                        methodValue = resolveId(context, id);
-                    } else {
-                        final FlagToString[] flagsMapping = property.flagMapping();
-                        if (flagsMapping.length > 0) {
-                            final int intValue = (Integer) methodValue;
-                            final String valuePrefix =
-                                    categoryPrefix + prefix + method.getName() + '_';
-                            exportUnrolledFlags(out, flagsMapping, intValue, valuePrefix);
-                        }
-
-                        final IntToString[] mapping = property.mapping();
-                        if (mapping.length > 0) {
-                            final int intValue = (Integer) methodValue;
-                            boolean mapped = false;
-                            int mappingCount = mapping.length;
-                            for (int j = 0; j < mappingCount; j++) {
-                                final IntToString mapper = mapping[j];
-                                if (mapper.from() == intValue) {
-                                    methodValue = mapper.to();
-                                    mapped = true;
-                                    break;
-                                }
-                            }
-
-                            if (!mapped) {
-                                methodValue = intValue;
-                            }
-                        }
-                    }
-                } else if (returnType == int[].class) {
-                    final int[] array = (int[]) methodValue;
-                    final String valuePrefix = categoryPrefix + prefix + method.getName() + '_';
-                    final String suffix = "()";
-
-                    exportUnrolledArray(context, out, property, array, valuePrefix, suffix);
-
-                    continue;
-                } else if (returnType == String[].class) {
-                    final String[] array = (String[]) methodValue;
-                    if (property.hasAdjacentMapping() && array != null) {
-                        for (int j = 0; j < array.length; j += 2) {
-                            if (array[j] != null) {
-                                writeEntry(out, categoryPrefix + prefix, array[j], "()",
-                                        array[j + 1] == null ? "null" : array[j + 1]);
-                            }
-
-                        }
-                    }
-
-                    continue;
-                } else if (!returnType.isPrimitive()) {
-                    if (property.deepExport()) {
-                        dumpViewProperties(context, methodValue, out, prefix + property.prefix());
-                        continue;
-                    }
-                }
-
-                writeEntry(out, categoryPrefix + prefix, method.getName(), "()", methodValue);
-            } catch (IllegalAccessException e) {
-            } catch (InvocationTargetException e) {
-            } catch (TimeoutException e) {
+                value = info.invoke(view);
+            } catch (Exception e) {
+                // ignore
+                continue;
             }
-        }
-    }
 
-    private static void exportFields(Context context, Object view, BufferedWriter out,
-            Class<?> klass, String prefix) throws IOException {
+            String categoryPrefix =
+                    info.property.category().length() != 0 ? info.property.category() + ":" : "";
 
-        final Field[] fields = getExportedPropertyFields(klass);
+            if (info.returnType == int.class || info.returnType == byte.class) {
+                if (info.property.resolveId() && context != null) {
+                    final int id = (Integer) value;
+                    value = resolveId(context, id);
 
-        int count = fields.length;
-        for (int i = 0; i < count; i++) {
-            final Field field = fields[i];
-
-            //noinspection EmptyCatchBlock
-            try {
-                Object fieldValue = null;
-                final Class<?> type = field.getType();
-                final ExportedProperty property = sAnnotations.get(field);
-                String categoryPrefix =
-                        property.category().length() != 0 ? property.category() + ":" : "";
-
-                if (type == int.class || type == byte.class) {
-                    if (property.resolveId() && context != null) {
-                        final int id = field.getInt(view);
-                        fieldValue = resolveId(context, id);
-                    } else {
-                        final FlagToString[] flagsMapping = property.flagMapping();
-                        if (flagsMapping.length > 0) {
-                            final int intValue = field.getInt(view);
-                            final String valuePrefix =
-                                    categoryPrefix + prefix + field.getName() + '_';
-                            exportUnrolledFlags(out, flagsMapping, intValue, valuePrefix);
-                        }
-
-                        final IntToString[] mapping = property.mapping();
-                        if (mapping.length > 0) {
-                            final int intValue = field.getInt(view);
-                            int mappingCount = mapping.length;
-                            for (int j = 0; j < mappingCount; j++) {
-                                final IntToString mapped = mapping[j];
-                                if (mapped.from() == intValue) {
-                                    fieldValue = mapped.to();
-                                    break;
-                                }
-                            }
-
-                            if (fieldValue == null) {
-                                fieldValue = intValue;
-                            }
-                        }
-
-                        if (property.formatToHexString()) {
-                            fieldValue = field.get(view);
-                            if (type == int.class) {
-                                fieldValue = formatIntToHexString((Integer) fieldValue);
-                            } else if (type == byte.class) {
-                                fieldValue = "0x"
-                                        + HexEncoding.encodeToString((Byte) fieldValue, true);
-                            }
-                        }
+                } else if (info.property.formatToHexString()) {
+                    if (info.returnType == int.class) {
+                        value = formatIntToHexString((Integer) value);
+                    } else if (info.returnType == byte.class) {
+                        value = "0x"
+                                + HexEncoding.encodeToString((Byte) value, true);
                     }
-                } else if (type == int[].class) {
-                    final int[] array = (int[]) field.get(view);
-                    final String valuePrefix = categoryPrefix + prefix + field.getName() + '_';
-                    final String suffix = "";
-
-                    exportUnrolledArray(context, out, property, array, valuePrefix, suffix);
-
-                    continue;
-                } else if (type == String[].class) {
-                    final String[] array = (String[]) field.get(view);
-                    if (property.hasAdjacentMapping() && array != null) {
-                        for (int j = 0; j < array.length; j += 2) {
-                            if (array[j] != null) {
-                                writeEntry(out, categoryPrefix + prefix, array[j], "",
-                                        array[j + 1] == null ? "null" : array[j + 1]);
-                            }
-                        }
+                } else {
+                    final ViewDebug.FlagToString[] flagsMapping = info.property.flagMapping();
+                    if (flagsMapping.length > 0) {
+                        final int intValue = (Integer) value;
+                        final String valuePrefix =
+                                categoryPrefix + prefix + info.name + '_';
+                        exportUnrolledFlags(out, flagsMapping, intValue, valuePrefix);
                     }
 
-                    continue;
-                } else if (!type.isPrimitive()) {
-                    if (property.deepExport()) {
-                        dumpViewProperties(context, field.get(view), out, prefix +
-                                property.prefix());
-                        continue;
+                    final ViewDebug.IntToString[] mapping = info.property.mapping();
+                    if (mapping.length > 0) {
+                        final int intValue = (Integer) value;
+                        boolean mapped = false;
+                        int mappingCount = mapping.length;
+                        for (int j = 0; j < mappingCount; j++) {
+                            final ViewDebug.IntToString mapper = mapping[j];
+                            if (mapper.from() == intValue) {
+                                value = mapper.to();
+                                mapped = true;
+                                break;
+                            }
+                        }
+
+                        if (!mapped) {
+                            value = intValue;
+                        }
+                    }
+                }
+            } else if (info.returnType == int[].class) {
+                final int[] array = (int[]) value;
+                final String valuePrefix = categoryPrefix + prefix + info.name + '_';
+                exportUnrolledArray(context, out, info.property, array, valuePrefix,
+                        info.entrySuffix);
+
+                continue;
+            } else if (info.returnType == String[].class) {
+                final String[] array = (String[]) value;
+                if (info.property.hasAdjacentMapping() && array != null) {
+                    for (int j = 0; j < array.length; j += 2) {
+                        if (array[j] != null) {
+                            writeEntry(out, categoryPrefix + prefix, array[j],
+                                    info.entrySuffix, array[j + 1] == null ? "null" : array[j + 1]);
+                        }
                     }
                 }
 
-                if (fieldValue == null) {
-                    fieldValue = field.get(view);
+                continue;
+            } else if (!info.returnType.isPrimitive()) {
+                if (info.property.deepExport()) {
+                    dumpViewProperties(context, value, out, prefix + info.property.prefix());
+                    continue;
                 }
-
-                writeEntry(out, categoryPrefix + prefix, field.getName(), "", fieldValue);
-            } catch (IllegalAccessException e) {
             }
+
+            writeEntry(out, categoryPrefix + prefix, info.name, info.entrySuffix, value);
         }
     }
 
@@ -1721,91 +1670,40 @@
         }
     }
 
-    private static Field[] capturedViewGetPropertyFields(Class<?> klass) {
-        if (mCapturedViewFieldsForClasses == null) {
-            mCapturedViewFieldsForClasses = new HashMap<Class<?>, Field[]>();
+    private static PropertyInfo<CapturedViewProperty, ?>[] getCapturedViewProperties(
+            Class<?> klass) {
+        if (sCapturedViewProperties == null) {
+            sCapturedViewProperties = new HashMap<>();
         }
-        final HashMap<Class<?>, Field[]> map = mCapturedViewFieldsForClasses;
+        final HashMap<Class<?>, PropertyInfo<CapturedViewProperty, ?>[]> map =
+                sCapturedViewProperties;
 
-        Field[] fields = map.get(klass);
-        if (fields != null) {
-            return fields;
+        PropertyInfo<CapturedViewProperty, ?>[] infos = map.get(klass);
+        if (infos == null) {
+            infos = convertToPropertyInfos(klass.getMethods(), klass.getFields(),
+                    CapturedViewProperty.class);
+            map.put(klass, infos);
         }
-
-        final ArrayList<Field> foundFields = new ArrayList<Field>();
-        fields = klass.getFields();
-
-        int count = fields.length;
-        for (int i = 0; i < count; i++) {
-            final Field field = fields[i];
-            if (field.isAnnotationPresent(CapturedViewProperty.class)) {
-                field.setAccessible(true);
-                foundFields.add(field);
-            }
-        }
-
-        fields = foundFields.toArray(new Field[foundFields.size()]);
-        map.put(klass, fields);
-
-        return fields;
+        return infos;
     }
 
-    private static Method[] capturedViewGetPropertyMethods(Class<?> klass) {
-        if (mCapturedViewMethodsForClasses == null) {
-            mCapturedViewMethodsForClasses = new HashMap<Class<?>, Method[]>();
-        }
-        final HashMap<Class<?>, Method[]> map = mCapturedViewMethodsForClasses;
-
-        Method[] methods = map.get(klass);
-        if (methods != null) {
-            return methods;
-        }
-
-        final ArrayList<Method> foundMethods = new ArrayList<Method>();
-        methods = klass.getMethods();
-
-        int count = methods.length;
-        for (int i = 0; i < count; i++) {
-            final Method method = methods[i];
-            if (method.getParameterTypes().length == 0 &&
-                    method.isAnnotationPresent(CapturedViewProperty.class) &&
-                    method.getReturnType() != Void.class) {
-                method.setAccessible(true);
-                foundMethods.add(method);
-            }
-        }
-
-        methods = foundMethods.toArray(new Method[foundMethods.size()]);
-        map.put(klass, methods);
-
-        return methods;
-    }
-
-    private static String capturedViewExportMethods(Object obj, Class<?> klass,
-            String prefix) {
-
+    private static String exportCapturedViewProperties(Object obj, Class<?> klass, String prefix) {
         if (obj == null) {
             return "null";
         }
 
         StringBuilder sb = new StringBuilder();
-        final Method[] methods = capturedViewGetPropertyMethods(klass);
 
-        int count = methods.length;
-        for (int i = 0; i < count; i++) {
-            final Method method = methods[i];
+        for (PropertyInfo<CapturedViewProperty, ?> pi : getCapturedViewProperties(klass)) {
             try {
-                Object methodValue = method.invoke(obj, (Object[]) null);
-                final Class<?> returnType = method.getReturnType();
+                Object methodValue = pi.invoke(obj);
 
-                CapturedViewProperty property = method.getAnnotation(CapturedViewProperty.class);
-                if (property.retrieveReturn()) {
+                if (pi.property.retrieveReturn()) {
                     //we are interested in the second level data only
-                    sb.append(capturedViewExportMethods(methodValue, returnType, method.getName() + "#"));
+                    sb.append(exportCapturedViewProperties(methodValue, pi.returnType,
+                            pi.name + "#"));
                 } else {
-                    sb.append(prefix);
-                    sb.append(method.getName());
-                    sb.append("()=");
+                    sb.append(prefix).append(pi.name).append(pi.entrySuffix).append("=");
 
                     if (methodValue != null) {
                         final String value = methodValue.toString().replace("\n", "\\n");
@@ -1813,47 +1711,10 @@
                     } else {
                         sb.append("null");
                     }
-                    sb.append("; ");
+                    sb.append(pi.valueSuffix).append(" ");
                 }
-            } catch (IllegalAccessException e) {
-                //Exception IllegalAccess, it is OK here
-                //we simply ignore this method
-            } catch (InvocationTargetException e) {
-                //Exception InvocationTarget, it is OK here
-                //we simply ignore this method
-            }
-        }
-        return sb.toString();
-    }
-
-    private static String capturedViewExportFields(Object obj, Class<?> klass, String prefix) {
-        if (obj == null) {
-            return "null";
-        }
-
-        StringBuilder sb = new StringBuilder();
-        final Field[] fields = capturedViewGetPropertyFields(klass);
-
-        int count = fields.length;
-        for (int i = 0; i < count; i++) {
-            final Field field = fields[i];
-            try {
-                Object fieldValue = field.get(obj);
-
-                sb.append(prefix);
-                sb.append(field.getName());
-                sb.append("=");
-
-                if (fieldValue != null) {
-                    final String value = fieldValue.toString().replace("\n", "\\n");
-                    sb.append(value);
-                } else {
-                    sb.append("null");
-                }
-                sb.append(' ');
-            } catch (IllegalAccessException e) {
-                //Exception IllegalAccess, it is OK here
-                //we simply ignore this field
+            } catch (Exception e) {
+                //It is OK here, we simply ignore this property
             }
         }
         return sb.toString();
@@ -1869,8 +1730,7 @@
     public static void dumpCapturedView(String tag, Object view) {
         Class<?> klass = view.getClass();
         StringBuilder sb = new StringBuilder(klass.getName() + ": ");
-        sb.append(capturedViewExportFields(view, klass, ""));
-        sb.append(capturedViewExportMethods(view, klass, ""));
+        sb.append(exportCapturedViewProperties(view, klass, ""));
         Log.d(tag, sb.toString());
     }
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9ddd84f..20dc234 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4570,6 +4570,7 @@
     private static final int MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED = 32;
     private static final int MSG_LOCATION_IN_PARENT_DISPLAY_CHANGED = 33;
     private static final int MSG_SHOW_INSETS = 34;
+    private static final int MSG_HIDE_INSETS = 35;
 
 
     final class ViewRootHandler extends Handler {
@@ -4636,6 +4637,8 @@
                     return "MSG_LOCATION_IN_PARENT_DISPLAY_CHANGED";
                 case MSG_SHOW_INSETS:
                     return "MSG_SHOW_INSETS";
+                case MSG_HIDE_INSETS:
+                    return "MSG_HIDE_INSETS";
             }
             return super.getMessageName(message);
         }
@@ -4754,6 +4757,10 @@
                     mInsetsController.show(msg.arg1, msg.arg2 == 1);
                     break;
                 }
+                case MSG_HIDE_INSETS: {
+                    mInsetsController.hide(msg.arg1, msg.arg2 == 1);
+                    break;
+                }
                 case MSG_WINDOW_MOVED:
                     if (mAdded) {
                         final int w = mWinFrame.width();
@@ -7559,6 +7566,10 @@
         mHandler.obtainMessage(MSG_SHOW_INSETS, types, fromIme ? 1 : 0).sendToTarget();
     }
 
+    private void hideInsets(@InsetType int types, boolean fromIme) {
+        mHandler.obtainMessage(MSG_HIDE_INSETS, types, fromIme ? 1 : 0).sendToTarget();
+    }
+
     public void dispatchMoved(int newX, int newY) {
         if (DEBUG_LAYOUT) Log.v(mTag, "Window moved " + this + ": newX=" + newX + " newY=" + newY);
         if (mTranslator != null) {
@@ -8682,6 +8693,14 @@
         }
 
         @Override
+        public void hideInsets(@InsetType int types, boolean fromIme) {
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
+            if (viewAncestor != null) {
+                viewAncestor.hideInsets(types, fromIme);
+            }
+        }
+
+        @Override
         public void moved(int newX, int newY) {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 0b42cd9..db76bb6 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1680,8 +1680,9 @@
          * to determine its default behavior.
          *
          * {@hide} */
-        @UnsupportedAppUsage
-        public static final int PRIVATE_FLAG_SHOW_FOR_ALL_USERS = 0x00000010;
+        @SystemApi
+        @RequiresPermission(permission.INTERNAL_SYSTEM_WINDOW)
+        public static final int SYSTEM_FLAG_SHOW_FOR_ALL_USERS = 0x00000010;
 
         /**
          * Never animate position changes of the window.
@@ -1842,6 +1843,7 @@
         @Retention(RetentionPolicy.SOURCE)
         @IntDef(flag = true, prefix = { "SYSTEM_FLAG_" }, value = {
                 SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
+                SYSTEM_FLAG_SHOW_FOR_ALL_USERS,
         })
         public @interface SystemFlags {}
 
@@ -1863,8 +1865,8 @@
                         equals = PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS,
                         name = "WANTS_OFFSET_NOTIFICATIONS"),
                 @ViewDebug.FlagToString(
-                        mask = PRIVATE_FLAG_SHOW_FOR_ALL_USERS,
-                        equals = PRIVATE_FLAG_SHOW_FOR_ALL_USERS,
+                        mask = SYSTEM_FLAG_SHOW_FOR_ALL_USERS,
+                        equals = SYSTEM_FLAG_SHOW_FOR_ALL_USERS,
                         name = "SHOW_FOR_ALL_USERS"),
                 @ViewDebug.FlagToString(
                         mask = PRIVATE_FLAG_NO_MOVE_ANIMATION,
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 0817452..cc28840 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -707,10 +707,10 @@
         try {
             services = service.getEnabledAccessibilityServiceList(feedbackTypeFlags, userId);
             if (DEBUG) {
-                Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
+                Log.i(LOG_TAG, "Enabled AccessibilityServices " + services);
             }
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re);
+            Log.e(LOG_TAG, "Error while obtaining the enabled AccessibilityServices. ", re);
         }
         if (mAccessibilityPolicy != null) {
             services = mAccessibilityPolicy.getEnabledAccessibilityServiceList(
diff --git a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
index 925a589..0b15cd0 100644
--- a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
+++ b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
@@ -246,7 +246,7 @@
                 Toast warningToast = mFrameworkObjectProvider.makeToastFromText(
                         mContext, toastMessage, Toast.LENGTH_LONG);
                 warningToast.getWindowParams().privateFlags |=
-                        WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+                        WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
                 warningToast.show();
             }
 
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index cae1f38..00c1e29 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -2576,6 +2576,34 @@
             }
         }
 
+        /**
+         * Rather than fully sorting the input list, this sorting task will put the top k elements
+         * in the head of input list and fill the tail with other elements in undetermined order.
+         */
+        @Override
+        AsyncTask<List<ResolvedComponentInfo>,
+                Void,
+                List<ResolvedComponentInfo>> createSortingTask() {
+            return new AsyncTask<List<ResolvedComponentInfo>,
+                    Void,
+                    List<ResolvedComponentInfo>>() {
+                @Override
+                protected List<ResolvedComponentInfo> doInBackground(
+                        List<ResolvedComponentInfo>... params) {
+                    mResolverListController.topK(params[0],
+                            getMaxRankedTargets());
+                    return params[0];
+                }
+
+                @Override
+                protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
+                    processSortedList(sortedComponents);
+                    bindProfileView();
+                    notifyDataSetChanged();
+                }
+            };
+        }
+
         @Override
         public void onListRebuilt() {
             updateAlphabeticalList();
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 8f6c950..3ab0b0d2 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -31,25 +31,27 @@
     // be kept in sync with frameworks/native/libs/binder/include/binder/IAppOpsService.h
     // and not be reordered
     int checkOperation(int code, int uid, String packageName);
-    int noteOperation(int code, int uid, String packageName);
-    int startOperation(IBinder token, int code, int uid, String packageName,
+    int noteOperation(int code, int uid, String packageName, String featureId);
+    int startOperation(IBinder token, int code, int uid, String packageName, String featureId,
             boolean startIfModeDefault);
     @UnsupportedAppUsage
-    void finishOperation(IBinder token, int code, int uid, String packageName);
+    void finishOperation(IBinder token, int code, int uid, String packageName,
+            String featureId);
     void startWatchingMode(int op, String packageName, IAppOpsCallback callback);
     void stopWatchingMode(IAppOpsCallback callback);
     IBinder getToken(IBinder clientToken);
     int permissionToOpCode(String permission);
     int checkAudioOperation(int code, int usage, int uid, String packageName);
     void noteAsyncOp(String callingPackageName, int uid, String packageName, int opCode,
-            String message);
+            String featureId, String message);
     boolean shouldCollectNotes(int opCode);
     void setCameraAudioRestriction(int mode);
     // End of methods also called by native code.
     // Any new method exposed to native must be added after the last one, do not reorder
 
-    int noteProxyOperation(int code, int proxyUid, String proxyPackageName,
-                int callingUid, String callingPackageName);
+    int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
+            String proxiedFeatureId, int proxyUid, String proxyPackageName,
+            String proxyFeatureId);
 
     // Remaining methods are only used in Java.
     int checkPackage(int uid, String packageName);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 068056f..7f18ae3 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1624,7 +1624,7 @@
         private final List<ResolveInfo> mBaseResolveList;
         protected ResolveInfo mLastChosen;
         private DisplayResolveInfo mOtherProfile;
-        private ResolverListController mResolverListController;
+        ResolverListController mResolverListController;
         private int mPlaceholderCount;
         private boolean mAllTargetsAreBrowsers = false;
 
@@ -1785,27 +1785,7 @@
                         --placeholderCount;
                     }
                     setPlaceholderCount(placeholderCount);
-                    AsyncTask<List<ResolvedComponentInfo>,
-                            Void,
-                            List<ResolvedComponentInfo>> sortingTask =
-                            new AsyncTask<List<ResolvedComponentInfo>,
-                                    Void,
-                                    List<ResolvedComponentInfo>>() {
-                        @Override
-                        protected List<ResolvedComponentInfo> doInBackground(
-                                List<ResolvedComponentInfo>... params) {
-                            mResolverListController.sort(params[0]);
-                            return params[0];
-                        }
-
-                        @Override
-                        protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
-                            processSortedList(sortedComponents);
-                            bindProfileView();
-                            notifyDataSetChanged();
-                        }
-                    };
-                    sortingTask.execute(currentResolveList);
+                    createSortingTask().execute(currentResolveList);
                     postListReadyRunnable();
                     return false;
                 } else {
@@ -1818,8 +1798,29 @@
             }
         }
 
+        AsyncTask<List<ResolvedComponentInfo>,
+                Void,
+                List<ResolvedComponentInfo>> createSortingTask() {
+            return new AsyncTask<List<ResolvedComponentInfo>,
+                    Void,
+                    List<ResolvedComponentInfo>>() {
+                @Override
+                protected List<ResolvedComponentInfo> doInBackground(
+                        List<ResolvedComponentInfo>... params) {
+                    mResolverListController.sort(params[0]);
+                    return params[0];
+                }
 
-        private void processSortedList(List<ResolvedComponentInfo> sortedComponents) {
+                @Override
+                protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
+                    processSortedList(sortedComponents);
+                    bindProfileView();
+                    notifyDataSetChanged();
+                }
+            };
+        }
+
+        void processSortedList(List<ResolvedComponentInfo> sortedComponents) {
             int N;
             if (sortedComponents != null && (N = sortedComponents.size()) != 0) {
                 mAllTargetsAreBrowsers = mUseLayoutForBrowsables;
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index a390611..b9a92b5 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -35,6 +35,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.PriorityQueue;
 import java.util.concurrent.CountDownLatch;
 
 /**
@@ -230,22 +231,27 @@
         }
     }
 
-    @VisibleForTesting
-    @WorkerThread
-    public void sort(List<ResolverActivity.ResolvedComponentInfo> inputList) {
+    private void compute(List<ResolverActivity.ResolvedComponentInfo> inputList)
+            throws InterruptedException {
         if (mResolverComparator == null) {
             Log.d(TAG, "Comparator has already been destroyed; skipped.");
             return;
         }
+        final CountDownLatch finishComputeSignal = new CountDownLatch(1);
+        ComputeCallback callback = new ComputeCallback(finishComputeSignal);
+        mResolverComparator.setCallBack(callback);
+        mResolverComparator.compute(inputList);
+        finishComputeSignal.await();
+        isComputed = true;
+    }
+
+    @VisibleForTesting
+    @WorkerThread
+    public void sort(List<ResolverActivity.ResolvedComponentInfo> inputList) {
         try {
             long beforeRank = System.currentTimeMillis();
             if (!isComputed) {
-                final CountDownLatch finishComputeSignal = new CountDownLatch(1);
-                ComputeCallback callback = new ComputeCallback(finishComputeSignal);
-                mResolverComparator.setCallBack(callback);
-                mResolverComparator.compute(inputList);
-                finishComputeSignal.await();
-                isComputed = true;
+                compute(inputList);
             }
             Collections.sort(inputList, mResolverComparator);
 
@@ -258,6 +264,60 @@
         }
     }
 
+    @VisibleForTesting
+    @WorkerThread
+    public void topK(List<ResolverActivity.ResolvedComponentInfo> inputList, int k) {
+        if (inputList == null || inputList.isEmpty() || k <= 0) {
+            return;
+        }
+        if (inputList.size() <= k) {
+            // Fall into normal sort when number of ranked elements
+            // needed is not smaller than size of input list.
+            sort(inputList);
+        }
+        try {
+            long beforeRank = System.currentTimeMillis();
+            if (!isComputed) {
+                compute(inputList);
+            }
+
+            // Top of this heap has lowest rank.
+            PriorityQueue<ResolverActivity.ResolvedComponentInfo> minHeap = new PriorityQueue<>(k,
+                    (o1, o2) -> -mResolverComparator.compare(o1, o2));
+            final int size = inputList.size();
+            // Use this pointer to keep track of the position of next element
+            // to update in input list, starting from the last position.
+            int pointer = size - 1;
+            minHeap.addAll(inputList.subList(size - k, size));
+            for (int i = size - k - 1; i >= 0; --i) {
+                ResolverActivity.ResolvedComponentInfo ci = inputList.get(i);
+                if (-mResolverComparator.compare(ci, minHeap.peek()) > 0) {
+                    // When ranked higher than top of heap, remove top of heap,
+                    // update input list with it, add this new element to heap.
+                    inputList.set(pointer--, minHeap.poll());
+                    minHeap.add(ci);
+                } else {
+                    // When ranked no higher than top of heap, update input list
+                    // with this new element.
+                    inputList.set(pointer--, ci);
+                }
+            }
+
+            // Now we have top k elements in heap, update first
+            // k positions of input list with them.
+            while (!minHeap.isEmpty()) {
+                inputList.set(pointer--, minHeap.poll());
+            }
+
+            long afterRank = System.currentTimeMillis();
+            if (DEBUG) {
+                Log.d(TAG, "Time Cost for top " + k + " targets: "
+                        + Long.toString(afterRank - beforeRank));
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "Compute & greatestOf was interrupted: " + e);
+        }
+    }
 
     private static boolean isSameResolvedComponent(ResolveInfo a,
             ResolverActivity.ResolvedComponentInfo b) {
diff --git a/core/java/com/android/internal/app/procstats/AssociationState.java b/core/java/com/android/internal/app/procstats/AssociationState.java
index 0ed2524..1d4239f 100644
--- a/core/java/com/android/internal/app/procstats/AssociationState.java
+++ b/core/java/com/android/internal/app/procstats/AssociationState.java
@@ -950,6 +950,14 @@
 
         proto.write(PackageAssociationProcessStatsProto.COMPONENT_NAME, mName);
 
+        proto.write(PackageAssociationProcessStatsProto.TOTAL_COUNT, mTotalCount);
+        proto.write(PackageAssociationProcessStatsProto.TOTAL_DURATION_MS, getTotalDuration(now));
+        if (mTotalActiveCount != 0) {
+            proto.write(PackageAssociationProcessStatsProto.ACTIVE_COUNT, mTotalActiveCount);
+            proto.write(PackageAssociationProcessStatsProto.ACTIVE_DURATION_MS,
+                    getActiveDuration(now));
+        }
+
         final int NSRC = mSources.size();
         for (int isrc = 0; isrc < NSRC; isrc++) {
             final SourceKey key = mSources.keyAt(isrc);
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index cdb79ab..f5708a5c 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -17,6 +17,7 @@
 package com.android.internal.content;
 
 import android.annotation.CallSuper;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ContentResolver;
 import android.content.Intent;
@@ -552,6 +553,11 @@
                     flags |= Document.FLAG_SUPPORTS_DELETE;
                     flags |= Document.FLAG_SUPPORTS_RENAME;
                     flags |= Document.FLAG_SUPPORTS_MOVE;
+
+                    if (shouldBlockFromTree(docId)) {
+                        flags |= Document.FLAG_DIR_BLOCKS_TREE;
+                    }
+
                 } else {
                     flags |= Document.FLAG_SUPPORTS_WRITE;
                     flags |= Document.FLAG_SUPPORTS_DELETE;
@@ -592,6 +598,10 @@
         return row;
     }
 
+    protected boolean shouldBlockFromTree(@NonNull String docId) {
+        return false;
+    }
+
     protected boolean typeSupportsMetadata(String mimeType) {
         return MetadataReader.isSupportedMimeType(mimeType)
                 || Document.MIME_TYPE_DIR.equals(mimeType);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 158700b..363e549 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -184,6 +184,12 @@
         System.loadLibrary("android");
         System.loadLibrary("compiler_rt");
         System.loadLibrary("jnigraphics");
+
+        try {
+            System.loadLibrary("sfplugin_ccodec");
+        } catch (Error | RuntimeException e) {
+            // tolerate missing sfplugin_ccodec which is only present on Codec 2 devices
+        }
     }
 
     native private static void nativePreloadAppProcessHALs();
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index a845b58..659134a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -17,6 +17,7 @@
 package com.android.internal.statusbar;
 
 import android.app.Notification;
+import android.net.Uri;
 import android.content.ComponentName;
 import android.graphics.Rect;
 import android.os.Bundle;
@@ -77,6 +78,7 @@
     void onNotificationSettingsViewed(String key);
     void setSystemUiVisibility(int displayId, int vis, int mask, String cause);
     void onNotificationBubbleChanged(String key, boolean isBubble);
+    void grantInlineReplyUriPermission(String key, in Uri uri);
 
     void onGlobalActionsShown();
     void onGlobalActionsHidden();
diff --git a/telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl b/core/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl
similarity index 100%
rename from telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl
rename to core/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
similarity index 99%
rename from telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
rename to core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 90019ee..084a3cc 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -29,6 +29,9 @@
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 
+/**
+ * {@hide}
+ */
 oneway interface IPhoneStateListener {
     void onServiceStateChanged(in ServiceState serviceState);
     void onSignalStrengthChanged(int asu);
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
similarity index 100%
rename from telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
rename to core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 0e078dd..7e1f13a 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -80,6 +80,10 @@
     }
 
     @Override
+    public void hideInsets(@InsetType int types, boolean fromIme)  throws RemoteException {
+    }
+
+    @Override
     public void moved(int newX, int newY) {
     }
 
diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java
index 09bc28c..85a45fd 100644
--- a/core/java/com/android/internal/widget/LockPatternChecker.java
+++ b/core/java/com/android/internal/widget/LockPatternChecker.java
@@ -1,13 +1,9 @@
 package com.android.internal.widget;
 
-import android.annotation.UnsupportedAppUsage;
 import android.os.AsyncTask;
 
 import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * Helper class to check/verify PIN/Password/Pattern asynchronously.
  */
@@ -53,34 +49,28 @@
     }
 
     /**
-     * Verify a pattern asynchronously.
+     * Verify a lockscreen credential asynchronously.
      *
      * @param utils The LockPatternUtils instance to use.
-     * @param pattern The pattern to check.
-     * @param challenge The challenge to verify against the pattern.
-     * @param userId The user to check against the pattern.
+     * @param credential The credential to check.
+     * @param challenge The challenge to verify against the credential.
+     * @param userId The user to check against the credential.
      * @param callback The callback to be invoked with the verification result.
      */
-    public static AsyncTask<?, ?, ?> verifyPattern(final LockPatternUtils utils,
-            final List<LockPatternView.Cell> pattern,
+    public static AsyncTask<?, ?, ?> verifyCredential(final LockPatternUtils utils,
+            final LockscreenCredential credential,
             final long challenge,
             final int userId,
             final OnVerifyCallback callback) {
+        // Create a copy of the credential since checking credential is asynchrounous.
+        final LockscreenCredential credentialCopy = credential.duplicate();
         AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
             private int mThrottleTimeout;
-            private List<LockPatternView.Cell> patternCopy;
-
-            @Override
-            protected void onPreExecute() {
-                // Make a copy of the pattern to prevent race conditions.
-                // No need to clone the individual cells because they are immutable.
-                patternCopy = new ArrayList(pattern);
-            }
 
             @Override
             protected byte[] doInBackground(Void... args) {
                 try {
-                    return utils.verifyPattern(patternCopy, challenge, userId);
+                    return utils.verifyCredential(credentialCopy, challenge, userId);
                 } catch (RequestThrottledException ex) {
                     mThrottleTimeout = ex.getTimeoutMs();
                     return null;
@@ -90,6 +80,12 @@
             @Override
             protected void onPostExecute(byte[] result) {
                 callback.onVerified(result, mThrottleTimeout);
+                credentialCopy.zeroize();
+            }
+
+            @Override
+            protected void onCancelled() {
+                credentialCopy.zeroize();
             }
         };
         task.execute();
@@ -97,32 +93,26 @@
     }
 
     /**
-     * Checks a pattern asynchronously.
+     * Checks a lockscreen credential asynchronously.
      *
      * @param utils The LockPatternUtils instance to use.
-     * @param pattern The pattern to check.
-     * @param userId The user to check against the pattern.
+     * @param credential The credential to check.
+     * @param userId The user to check against the credential.
      * @param callback The callback to be invoked with the check result.
      */
-    public static AsyncTask<?, ?, ?> checkPattern(final LockPatternUtils utils,
-            final List<LockPatternView.Cell> pattern,
+    public static AsyncTask<?, ?, ?> checkCredential(final LockPatternUtils utils,
+            final LockscreenCredential credential,
             final int userId,
             final OnCheckCallback callback) {
+        // Create a copy of the credential since checking credential is asynchrounous.
+        final LockscreenCredential credentialCopy = credential.duplicate();
         AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() {
             private int mThrottleTimeout;
-            private List<LockPatternView.Cell> patternCopy;
-
-            @Override
-            protected void onPreExecute() {
-                // Make a copy of the pattern to prevent race conditions.
-                // No need to clone the individual cells because they are immutable.
-                patternCopy = new ArrayList(pattern);
-            }
 
             @Override
             protected Boolean doInBackground(Void... args) {
                 try {
-                    return utils.checkPattern(patternCopy, userId, callback::onEarlyMatched);
+                    return utils.checkCredential(credentialCopy, userId, callback::onEarlyMatched);
                 } catch (RequestThrottledException ex) {
                     mThrottleTimeout = ex.getTimeoutMs();
                     return false;
@@ -132,11 +122,13 @@
             @Override
             protected void onPostExecute(Boolean result) {
                 callback.onChecked(result, mThrottleTimeout);
+                credentialCopy.zeroize();
             }
 
             @Override
             protected void onCancelled() {
                 callback.onCancelled();
+                credentialCopy.zeroize();
             }
         };
         task.execute();
@@ -144,84 +136,29 @@
     }
 
     /**
-     * Verify a password asynchronously.
+     * Perform a lockscreen credential verification explicitly on a managed profile with unified
+     * challenge, using the parent user's credential.
      *
      * @param utils The LockPatternUtils instance to use.
-     * @param password The password to check.
-     * @param challenge The challenge to verify against the pattern.
-     * @param userId The user to check against the pattern.
-     * @param callback The callback to be invoked with the verification result.
-     *
-     * @deprecated Pass the password as a byte array.
-     */
-    @Deprecated
-    public static AsyncTask<?, ?, ?> verifyPassword(final LockPatternUtils utils,
-            final String password,
-            final long challenge,
-            final int userId,
-            final OnVerifyCallback callback) {
-        byte[] passwordBytes = password != null ? password.getBytes() : null;
-        return verifyPassword(utils, passwordBytes, challenge, userId, callback);
-    }
-
-    /**
-     * Verify a password asynchronously.
-     *
-     * @param utils The LockPatternUtils instance to use.
-     * @param password The password to check.
-     * @param challenge The challenge to verify against the pattern.
-     * @param userId The user to check against the pattern.
-     * @param callback The callback to be invoked with the verification result.
-     */
-    public static AsyncTask<?, ?, ?> verifyPassword(final LockPatternUtils utils,
-            final byte[] password,
-            final long challenge,
-            final int userId,
-            final OnVerifyCallback callback) {
-        AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
-            private int mThrottleTimeout;
-
-            @Override
-            protected byte[] doInBackground(Void... args) {
-                try {
-                    return utils.verifyPassword(password, challenge, userId);
-                } catch (RequestThrottledException ex) {
-                    mThrottleTimeout = ex.getTimeoutMs();
-                    return null;
-                }
-            }
-
-            @Override
-            protected void onPostExecute(byte[] result) {
-                callback.onVerified(result, mThrottleTimeout);
-            }
-        };
-        task.execute();
-        return task;
-    }
-
-    /**
-     * Verify a password asynchronously.
-     *
-     * @param utils The LockPatternUtils instance to use.
-     * @param password The password to check.
-     * @param challenge The challenge to verify against the pattern.
-     * @param userId The user to check against the pattern.
+     * @param credential The credential to check.
+     * @param challenge The challenge to verify against the credential.
+     * @param userId The user to check against the credential.
      * @param callback The callback to be invoked with the verification result.
      */
     public static AsyncTask<?, ?, ?> verifyTiedProfileChallenge(final LockPatternUtils utils,
-            final byte[] password,
-            final boolean isPattern,
+            final LockscreenCredential credential,
             final long challenge,
             final int userId,
             final OnVerifyCallback callback) {
+        // Create a copy of the credential since checking credential is asynchrounous.
+        final LockscreenCredential credentialCopy = credential.duplicate();
         AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
             private int mThrottleTimeout;
 
             @Override
             protected byte[] doInBackground(Void... args) {
                 try {
-                    return utils.verifyTiedProfileChallenge(password, isPattern, challenge, userId);
+                    return utils.verifyTiedProfileChallenge(credentialCopy, challenge, userId);
                 } catch (RequestThrottledException ex) {
                     mThrottleTimeout = ex.getTimeoutMs();
                     return null;
@@ -231,64 +168,12 @@
             @Override
             protected void onPostExecute(byte[] result) {
                 callback.onVerified(result, mThrottleTimeout);
-            }
-        };
-        task.execute();
-        return task;
-    }
-
-    /**
-     * Checks a password asynchronously.
-     *
-     * @param utils The LockPatternUtils instance to use.
-     * @param password The password to check.
-     * @param userId The user to check against the pattern.
-     * @param callback The callback to be invoked with the check result.
-     * @deprecated Pass passwords as byte[]
-     */
-    @UnsupportedAppUsage
-    @Deprecated
-    public static AsyncTask<?, ?, ?> checkPassword(final LockPatternUtils utils,
-            final String password,
-            final int userId,
-            final OnCheckCallback callback) {
-        byte[] passwordBytes = password != null ? password.getBytes() : null;
-        return checkPassword(utils, passwordBytes, userId, callback);
-    }
-
-    /**
-     * Checks a password asynchronously.
-     *
-     * @param utils The LockPatternUtils instance to use.
-     * @param passwordBytes The password to check.
-     * @param userId The user to check against the pattern.
-     * @param callback The callback to be invoked with the check result.
-     */
-    public static AsyncTask<?, ?, ?> checkPassword(final LockPatternUtils utils,
-            final byte[] passwordBytes,
-            final int userId,
-            final OnCheckCallback callback) {
-        AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() {
-            private int mThrottleTimeout;
-
-            @Override
-            protected Boolean doInBackground(Void... args) {
-                try {
-                    return utils.checkPassword(passwordBytes, userId, callback::onEarlyMatched);
-                } catch (RequestThrottledException ex) {
-                    mThrottleTimeout = ex.getTimeoutMs();
-                    return false;
-                }
-            }
-
-            @Override
-            protected void onPostExecute(Boolean result) {
-                callback.onChecked(result, mThrottleTimeout);
+                credentialCopy.zeroize();
             }
 
             @Override
             protected void onCancelled() {
-                callback.onCancelled();
+                credentialCopy.zeroize();
             }
         };
         task.execute();
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 070121c..8fea703 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -26,6 +26,7 @@
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.app.admin.DevicePolicyManager;
@@ -58,10 +59,10 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
 
-import com.google.android.collect.Lists;
-
 import libcore.util.HexEncoding;
 
+import com.google.android.collect.Lists;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.security.MessageDigest;
@@ -77,7 +78,6 @@
  * Utilities for the lock pattern and its settings.
  */
 public class LockPatternUtils {
-
     private static final String TAG = "LockPatternUtils";
     private static final boolean FRP_CREDENTIAL_ENABLED = true;
 
@@ -114,6 +114,7 @@
      */
     public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE;
 
+    // NOTE: When modifying this, make sure credential sufficiency validation logic is intact.
     public static final int CREDENTIAL_TYPE_NONE = -1;
     public static final int CREDENTIAL_TYPE_PATTERN = 1;
     public static final int CREDENTIAL_TYPE_PASSWORD = 2;
@@ -289,10 +290,10 @@
         return getDevicePolicyManager().getPasswordMaximumLength(quality);
     }
 
-    /**
-     * Gets the device policy password mode. If the mode is non-specific, returns
-     * MODE_PATTERN which allows the user to choose anything.
-     */
+    public PasswordMetrics getRequestedPasswordMetrics(int userId) {
+        return getDevicePolicyManager().getPasswordMinimumMetrics(userId);
+    }
+
     public int getRequestedPasswordQuality(int userId) {
         return getDevicePolicyManager().getPasswordQuality(null, userId);
     }
@@ -365,11 +366,24 @@
                 null /* componentName */, userId);
     }
 
-    private byte[] verifyCredential(byte[] credential, int type, long challenge, int userId)
-            throws RequestThrottledException {
+    /**
+     * Check to see if a credential matches the saved one.
+     * If credential matches, return an opaque attestation that the challenge was verified.
+     *
+     * @param credential The credential to check.
+     * @param challenge The challenge to verify against the credential
+     * @return the attestation that the challenge was verified, or null
+     * @param userId The user whose credential is being verified
+     * @throws RequestThrottledException if credential verification is being throttled due to
+     *         to many incorrect attempts.
+     * @throws IllegalStateException if called on the main thread.
+     */
+    public byte[] verifyCredential(@NonNull LockscreenCredential credential, long challenge,
+            int userId) throws RequestThrottledException {
+        throwIfCalledOnMainThread();
         try {
-            VerifyCredentialResponse response = getLockSettings().verifyCredential(credential,
-                    type, challenge, userId);
+            VerifyCredentialResponse response = getLockSettings().verifyCredential(
+                    credential.getCredential(), credential.getType(), challenge, userId);
             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
                 return response.getPayload();
             } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
@@ -382,11 +396,24 @@
         }
     }
 
-    private boolean checkCredential(byte[] credential, int type, int userId,
+    /**
+     * Check to see if a credential matches the saved one.
+     *
+     * @param credential The credential to check.
+     * @param userId The user whose credential is being checked
+     * @param progressCallback callback to deliver early signal that the credential matches
+     * @return {@code true} if credential matches, {@code false} otherwise
+     * @throws RequestThrottledException if credential verification is being throttled due to
+     *         to many incorrect attempts.
+     * @throws IllegalStateException if called on the main thread.
+     */
+    public boolean checkCredential(@NonNull LockscreenCredential credential, int userId,
             @Nullable CheckCredentialProgressCallback progressCallback)
             throws RequestThrottledException {
+        throwIfCalledOnMainThread();
         try {
-            VerifyCredentialResponse response = getLockSettings().checkCredential(credential, type,
+            VerifyCredentialResponse response = getLockSettings().checkCredential(
+                    credential.getCredential(), credential.getType(),
                     userId, wrapCallback(progressCallback));
 
             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
@@ -402,79 +429,26 @@
     }
 
     /**
-     * Check to see if a pattern matches the saved pattern.
-     * If pattern matches, return an opaque attestation that the challenge
-     * was verified.
+     * Check if the credential of a managed profile with unified challenge matches. In this context,
+     * The credential should be the parent user's lockscreen password. If credential matches,
+     * return an opaque attestation associated with the managed profile that the challenge was
+     * verified.
      *
-     * @param pattern The pattern to check.
-     * @param challenge The challenge to verify against the pattern
-     * @return the attestation that the challenge was verified, or null.
+     * @param credential The parent user's credential to check.
+     * @param challenge The challenge to verify against the credential
+     * @return the attestation that the challenge was verified, or null
+     * @param userId The managed profile user id
+     * @throws RequestThrottledException if credential verification is being throttled due to
+     *         to many incorrect attempts.
+     * @throws IllegalStateException if called on the main thread.
      */
-    public byte[] verifyPattern(List<LockPatternView.Cell> pattern, long challenge, int userId)
-            throws RequestThrottledException {
-        throwIfCalledOnMainThread();
-        return verifyCredential(patternToByteArray(pattern), CREDENTIAL_TYPE_PATTERN, challenge,
-                userId);
-    }
-
-    /**
-     * Check to see if a pattern matches the saved pattern.  If no pattern exists,
-     * always returns true.
-     * @param pattern The pattern to check.
-     * @return Whether the pattern matches the stored one.
-     */
-    public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId)
-            throws RequestThrottledException {
-        return checkPattern(pattern, userId, null /* progressCallback */);
-    }
-
-    /**
-     * Check to see if a pattern matches the saved pattern.  If no pattern exists,
-     * always returns true.
-     * @param pattern The pattern to check.
-     * @return Whether the pattern matches the stored one.
-     */
-    public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId,
-            @Nullable CheckCredentialProgressCallback progressCallback)
-            throws RequestThrottledException {
-        throwIfCalledOnMainThread();
-        return checkCredential(patternToByteArray(pattern), CREDENTIAL_TYPE_PATTERN, userId,
-                progressCallback);
-    }
-
-    /**
-     * Check to see if a password matches the saved password.
-     * If password matches, return an opaque attestation that the challenge
-     * was verified.
-     *
-     * @param password The password to check.
-     * @param challenge The challenge to verify against the password
-     * @return the attestation that the challenge was verified, or null.
-     */
-    public byte[] verifyPassword(byte[] password, long challenge, int userId)
-            throws RequestThrottledException {
-        throwIfCalledOnMainThread();
-        return verifyCredential(password, CREDENTIAL_TYPE_PASSWORD, challenge, userId);
-    }
-
-
-    /**
-     * Check to see if a password matches the saved password.
-     * If password matches, return an opaque attestation that the challenge
-     * was verified.
-     *
-     * @param password The password to check.
-     * @param challenge The challenge to verify against the password
-     * @return the attestation that the challenge was verified, or null.
-     */
-    public byte[] verifyTiedProfileChallenge(byte[] password, boolean isPattern, long challenge,
-            int userId) throws RequestThrottledException {
+    public byte[] verifyTiedProfileChallenge(@NonNull LockscreenCredential credential,
+            long challenge, int userId) throws RequestThrottledException {
         throwIfCalledOnMainThread();
         try {
             VerifyCredentialResponse response =
-                    getLockSettings().verifyTiedProfileChallenge(password,
-                            isPattern ? CREDENTIAL_TYPE_PATTERN : CREDENTIAL_TYPE_PASSWORD, challenge,
-                            userId);
+                    getLockSettings().verifyTiedProfileChallenge(
+                            credential.getCredential(), credential.getType(), challenge, userId);
 
             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
                 return response.getPayload();
@@ -489,61 +463,6 @@
     }
 
     /**
-     *
-     * Check to see if a password matches the saved password.  If no password exists,
-     * always returns true.
-     * @param password The password to check.
-     * @return Whether the password matches the stored one.
-     */
-    @UnsupportedAppUsage
-    public boolean checkPassword(String password, int userId) throws RequestThrottledException {
-        byte[] passwordBytes = password != null ? password.getBytes() : null;
-        return checkPassword(passwordBytes, userId, null /* progressCallback */);
-    }
-
-
-    /**
-     *
-     * Check to see if a password matches the saved password.  If no password exists,
-     * always returns true.
-     * @param password The password to check.
-     * @return Whether the password matches the stored one.
-     */
-    public boolean checkPassword(byte[] password, int userId) throws RequestThrottledException {
-        return checkPassword(password, userId, null /* progressCallback */);
-    }
-
-    // TODO(b/120484642): This method is necessary for vendor/qcom code and is a hidden api
-    /* *
-     * Check to see if a password matches the saved password.  If no password exists,
-     * always returns true.
-     * @param password The password to check.
-     * @return Whether the password matches the stored one.
-     */
-    public boolean checkPassword(String password, int userId,
-            @Nullable CheckCredentialProgressCallback progressCallback)
-            throws RequestThrottledException {
-        byte[] passwordBytes = password != null ? password.getBytes() : null;
-        throwIfCalledOnMainThread();
-        return checkCredential(passwordBytes, CREDENTIAL_TYPE_PASSWORD, userId, progressCallback);
-
-    }
-
-    /**
-     * Check to see if a password matches the saved password.  If no password exists,
-     * always returns true.
-     * @param password The password to check.
-     * @return Whether the password matches the stored one.
-     */
-
-    public boolean checkPassword(byte[] password, int userId,
-            @Nullable CheckCredentialProgressCallback progressCallback)
-            throws RequestThrottledException {
-        throwIfCalledOnMainThread();
-        return checkCredential(password, CREDENTIAL_TYPE_PASSWORD, userId, progressCallback);
-    }
-
-    /**
      * Check to see if vold already has the password.
      * Note that this also clears vold's copy of the password.
      * @return Whether the vold password matches or not.
@@ -560,9 +479,10 @@
      * Returns the password history hash factor, needed to check new password against password
      * history with {@link #checkPasswordHistory(byte[], byte[], int)}
      */
-    public byte[] getPasswordHistoryHashFactor(byte[] currentPassword, int userId) {
+    public byte[] getPasswordHistoryHashFactor(@NonNull LockscreenCredential currentPassword,
+            int userId) {
         try {
-            return getLockSettings().getHashFactor(currentPassword, userId);
+            return getLockSettings().getHashFactor(currentPassword.getCredential(), userId);
         } catch (RemoteException e) {
             Log.e(TAG, "failed to get hash factor", e);
             return null;
@@ -679,57 +599,6 @@
     }
 
     /**
-     * Clear any lock pattern or password.
-
-     * <p> This method will fail (returning {@code false}) if the previously
-     * saved password provided is incorrect, or if the lockscreen verification
-     * is still being throttled.
-     *
-     * @param savedCredential The previously saved credential
-     * @param userHandle the user whose pattern is to be saved.
-     * @return whether this was successful or not.
-     * @throws RuntimeException if password change encountered an unrecoverable error.
-     */
-    public boolean clearLock(byte[] savedCredential, int userHandle) {
-        return clearLock(savedCredential, userHandle, false);
-    }
-
-    /**
-     * Clear any lock pattern or password, with the option to ignore incorrect existing credential.
-     * <p> This method will fail (returning {@code false}) if the previously
-     * saved password provided is incorrect, or if the lockscreen verification
-     * is still being throttled.
-     *
-     * @param savedCredential The previously saved credential
-     * @param userHandle the user whose pattern is to be saved.
-     * @return whether this was successful or not.
-     * @throws RuntimeException if password change encountered an unrecoverable error.
-     */
-    public boolean clearLock(byte[] savedCredential, int userHandle, boolean allowUntrustedChange) {
-        final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
-        setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED, userHandle);
-
-        try {
-            if (!getLockSettings().setLockCredential(null, CREDENTIAL_TYPE_NONE, savedCredential,
-                    PASSWORD_QUALITY_UNSPECIFIED, userHandle, allowUntrustedChange)) {
-                return false;
-            }
-        } catch (RemoteException | RuntimeException e) {
-            setKeyguardStoredPasswordQuality(currentQuality, userHandle);
-            throw new RuntimeException("Failed to clear lock", e);
-        }
-
-        if (userHandle == UserHandle.USER_SYSTEM) {
-            // Set the encryption password to default.
-            updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
-            setCredentialRequiredToDecrypt(false);
-        }
-
-        onAfterChangingPassword(userHandle);
-        return true;
-    }
-
-    /**
      * Disable showing lock screen at all for a given user.
      * This is only meaningful if pattern, pin or password are not set.
      *
@@ -762,75 +631,88 @@
                 || isDemoUser;
     }
 
-    /**
-     * Save a lock pattern.
-     *
-     * <p> This method will fail (returning {@code false}) if the previously saved pattern provided
-     * is incorrect, or if the lockscreen verification is still being throttled.
-     *
-     * @param pattern The new pattern to save.
-     * @param savedPattern The previously saved pattern, converted to byte[] format
-     * @param userId the user whose pattern is to be saved.
-     * @return whether this was successful or not.
-     * @throws RuntimeException if password change encountered an unrecoverable error.
-     */
-    public boolean saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern,
-            int userId) {
-        return saveLockPattern(pattern, savedPattern, userId, false);
+    /** Returns if the given quality maps to an alphabetic password */
+    public static boolean isQualityAlphabeticPassword(int quality) {
+        return quality >= PASSWORD_QUALITY_ALPHABETIC;
+    }
+
+    /** Returns if the given quality maps to an numeric pin */
+    public static boolean isQualityNumericPin(int quality) {
+        return quality == PASSWORD_QUALITY_NUMERIC || quality == PASSWORD_QUALITY_NUMERIC_COMPLEX;
     }
 
     /**
-     * Save a lock pattern.
+     * Save a new lockscreen credential.
      *
-     * <p> This method will fail (returning {@code false}) if the previously saved pattern provided
-     * is incorrect, or if the lockscreen verification is still being throttled.
+     * <p> This method will fail (returning {@code false}) if the previously saved credential
+     * provided is incorrect, or if the lockscreen verification is still being throttled.
      *
-     * @param pattern The new pattern to save.
-     * @param savedPattern The previously saved pattern, converted to byte[] format
-     * @param userId the user whose pattern is to be saved.
-     * @param allowUntrustedChange whether we want to allow saving a new password if the existing
-     * password being provided is incorrect.
-     * @return whether this was successful or not.
+     * @param newCredential The new credential to save
+     * @param savedCredential The current credential
+     * @param userId the user whose lockscreen credential is to be changed
+     *
+     * @return whether this method saved the new password successfully or not. This flow will fail
+     * and return false if the given credential is wrong.
      * @throws RuntimeException if password change encountered an unrecoverable error.
      */
-    public boolean saveLockPattern(List<LockPatternView.Cell> pattern, byte[] savedPattern,
-            int userId, boolean allowUntrustedChange) {
+    public boolean setLockCredential(@NonNull LockscreenCredential newCredential,
+            @NonNull LockscreenCredential savedCredential, int userId) {
+        return setLockCredential(newCredential, savedCredential, userId, false);
+    }
+
+    /**
+     * Save a new lockscreen credential.
+     * <p> This method will fail (returning {@code false}) if the previously saved pattern provided
+     * is incorrect and allowUntrustedChange is false, or if the lockscreen verification is still
+     * being throttled.
+     * @param newCredential The new credential to save
+     * @param savedCredential The current credential
+     * @param userHandle the user whose lockscreen credential is to be changed
+     * @param allowUntrustedChange whether we want to allow saving a new pattern if the existing
+     * credentialt being provided is incorrect.
+     *
+     * @return whether this method saved the new password successfully or not. This flow will fail
+     * and return false if the given credential is wrong and allowUntrustedChange is false.
+     * @throws RuntimeException if password change encountered an unrecoverable error.
+     */
+    public boolean setLockCredential(@NonNull LockscreenCredential newCredential,
+            @NonNull LockscreenCredential savedCredential, int userHandle,
+            boolean allowUntrustedChange) {
         if (!hasSecureLockScreen()) {
             throw new UnsupportedOperationException(
                     "This operation requires the lock screen feature.");
         }
-        if (pattern == null || pattern.size() < MIN_LOCK_PATTERN_SIZE) {
-            throw new IllegalArgumentException("pattern must not be null and at least "
-                    + MIN_LOCK_PATTERN_SIZE + " dots long.");
-        }
+        newCredential.checkLength();
 
-        final byte[] bytePattern = patternToByteArray(pattern);
-        final int currentQuality = getKeyguardStoredPasswordQuality(userId);
-        setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_SOMETHING, userId);
+        final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
+        setKeyguardStoredPasswordQuality(newCredential.getQuality(), userHandle);
+
         try {
-            if (!getLockSettings().setLockCredential(bytePattern, CREDENTIAL_TYPE_PATTERN,
-                    savedPattern, PASSWORD_QUALITY_SOMETHING, userId, allowUntrustedChange)) {
+            if (!getLockSettings().setLockCredential(
+                    newCredential.getCredential(), newCredential.getType(),
+                    savedCredential.getCredential(),
+                    newCredential.getQuality(), userHandle, allowUntrustedChange)) {
+                setKeyguardStoredPasswordQuality(currentQuality, userHandle);
                 return false;
             }
         } catch (RemoteException | RuntimeException e) {
-            setKeyguardStoredPasswordQuality(currentQuality, userId);
-            throw new RuntimeException("Couldn't save lock pattern", e);
-        }
-        // Update the device encryption password.
-        if (userId == UserHandle.USER_SYSTEM
-                && LockPatternUtils.isDeviceEncryptionEnabled()) {
-            if (!shouldEncryptWithCredentials(true)) {
-                clearEncryptionPassword();
-            } else {
-                updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, bytePattern);
-            }
+            setKeyguardStoredPasswordQuality(currentQuality, userHandle);
+            throw new RuntimeException("Unable to save lock password", e);
         }
 
-        reportPatternWasChosen(userId);
-        onAfterChangingPassword(userId);
+        onPostPasswordChanged(newCredential, userHandle);
         return true;
     }
 
+    private void onPostPasswordChanged(LockscreenCredential newCredential, int userHandle) {
+        updateEncryptionPasswordIfNeeded(newCredential, userHandle);
+        if (newCredential.isPattern()) {
+            reportPatternWasChosen(userHandle);
+        }
+        updatePasswordHistory(newCredential, userHandle);
+        reportEnabledTrustAgentsChanged(userHandle);
+    }
+
     private void updateCryptoUserInfo(int userId) {
         if (userId != UserHandle.USER_SYSTEM) {
             return;
@@ -929,149 +811,35 @@
     }
 
     /**
-     * Save a lock password.  Does not ensure that the password is as good
-     * as the requested mode, but will adjust the mode to be as good as the
-     * password.
-     *
-     * <p> This method will fail (returning {@code false}) if the previously
-     * saved password provided is incorrect, or if the lockscreen verification
-     * is still being throttled.
-     *
-     * @param password The password to save
-     * @param savedPassword The previously saved lock password, or null if none
-     * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality(
-     * android.content.ComponentName)}
-     * @param userHandle The userId of the user to change the password for
-     * @return whether this was successful or not.
-     * @throws RuntimeException if password change encountered an unrecoverable error.
-     * @deprecated Pass password as a byte array
-     */
-    @Deprecated
-    public boolean saveLockPassword(String password, String savedPassword, int requestedQuality,
-            int userHandle) {
-        byte[] passwordBytes = password != null ? password.getBytes() : null;
-        byte[] savedPasswordBytes = savedPassword != null ? savedPassword.getBytes() : null;
-        return saveLockPassword(passwordBytes, savedPasswordBytes, requestedQuality, userHandle);
-    }
-
-    /**
-     * Save a lock password.  Does not ensure that the password is as good
-     * as the requested mode, but will adjust the mode to be as good as the
-     * password.
-     *
-     * <p> This method will fail (returning {@code false}) if the previously
-     * saved password provided is incorrect, or if the lockscreen verification
-     * is still being throttled.
-     *
-     * @param password The password to save
-     * @param savedPassword The previously saved lock password, or null if none
-     * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality(
-     * android.content.ComponentName)}
-     * @param userHandle The userId of the user to change the password for
-     * @return whether this was successful or not.
-     * @throws RuntimeException if password change encountered an unrecoverable error.
-     */
-    public boolean saveLockPassword(byte[] password, byte[] savedPassword, int requestedQuality,
-            int userHandle) {
-        return saveLockPassword(password, savedPassword, requestedQuality,
-                userHandle, false);
-    }
-
-    /**
-     * Save a lock password.  Does not ensure that the password is as good
-     * as the requested mode, but will adjust the mode to be as good as the
-     * password.
-     *
-     * <p> This method will fail (returning {@code false}) if the previously
-     * saved password provided is incorrect, or if the lockscreen verification
-     * is still being throttled.
-     *
-     * @param password The password to save
-     * @param savedPassword The previously saved lock password, or null if none
-     * @param requestedQuality {@see DevicePolicyManager#getPasswordQuality(
-     * android.content.ComponentName)}
-     * @param userHandle The userId of the user to change the password for
-     * @param allowUntrustedChange whether we want to allow saving a new password if the existing
-     * password being provided is incorrect.
-     * @return whether this method saved the new password successfully or not. This flow will fail
-     * and return false if the given credential is wrong and allowUntrustedChange is false.
-     * @throws RuntimeException if password change encountered an unrecoverable error.
-     */
-    public boolean saveLockPassword(byte[] password, byte[] savedPassword,
-            int requestedQuality, int userHandle, boolean allowUntrustedChange) {
-        if (!hasSecureLockScreen()) {
-            throw new UnsupportedOperationException(
-                    "This operation requires the lock screen feature.");
-        }
-        if (password == null || password.length < MIN_LOCK_PASSWORD_SIZE) {
-            throw new IllegalArgumentException("password must not be null and at least "
-                    + "of length " + MIN_LOCK_PASSWORD_SIZE);
-        }
-
-        if (requestedQuality < PASSWORD_QUALITY_NUMERIC) {
-            throw new IllegalArgumentException("quality must be at least NUMERIC, but was "
-                    + requestedQuality);
-        }
-
-        final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
-        final int passwordQuality = PasswordMetrics.computeForPassword(password).quality;
-        final int newKeyguardQuality =
-                computeKeyguardQuality(CREDENTIAL_TYPE_PASSWORD, requestedQuality, passwordQuality);
-        setKeyguardStoredPasswordQuality(newKeyguardQuality, userHandle);
-        try {
-            getLockSettings().setLockCredential(password, CREDENTIAL_TYPE_PASSWORD, savedPassword,
-                    requestedQuality, userHandle, allowUntrustedChange);
-        } catch (RemoteException | RuntimeException e) {
-            setKeyguardStoredPasswordQuality(currentQuality, userHandle);
-            throw new RuntimeException("Unable to save lock password", e);
-        }
-
-        updateEncryptionPasswordIfNeeded(password, passwordQuality, userHandle);
-        updatePasswordHistory(password, userHandle);
-        onAfterChangingPassword(userHandle);
-        return true;
-    }
-
-    /**
-     * Compute keyguard credential quality to store in PASSWORD_TYPE_KEY by computing max between
-     * them so that digit-only password is distinguished from PIN.
-     *
-     * TODO: remove this method and make CREDENTIAL_TYPE distinguish between PIN and password, so
-     * that this quality is no longer needs to be persisted.
-     */
-    private int computeKeyguardQuality(
-            @CredentialType int credentialType, int requestedQuality, int passwordQuality) {
-        return credentialType == CREDENTIAL_TYPE_PASSWORD
-                ? Math.max(passwordQuality, requestedQuality) : passwordQuality;
-    }
-
-    /**
      * Update device encryption password if calling user is USER_SYSTEM and device supports
      * encryption.
      */
-    private void updateEncryptionPasswordIfNeeded(byte[] password, int quality, int userHandle) {
+    private void updateEncryptionPasswordIfNeeded(LockscreenCredential credential, int userHandle) {
         // Update the device encryption password.
-        if (userHandle == UserHandle.USER_SYSTEM
-                && LockPatternUtils.isDeviceEncryptionEnabled()) {
-            if (!shouldEncryptWithCredentials(true)) {
-                clearEncryptionPassword();
-            } else {
-                boolean numeric = quality == PASSWORD_QUALITY_NUMERIC;
-                boolean numericComplex = quality == PASSWORD_QUALITY_NUMERIC_COMPLEX;
-                int type = numeric || numericComplex ? StorageManager.CRYPT_TYPE_PIN
-                        : StorageManager.CRYPT_TYPE_PASSWORD;
-                updateEncryptionPassword(type, password);
-            }
+        if (userHandle != UserHandle.USER_SYSTEM || !isDeviceEncryptionEnabled()) {
+            return;
         }
+        if (!shouldEncryptWithCredentials(true)) {
+            updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
+            return;
+        }
+        if (credential.isNone()) {
+            // Set the encryption password to default.
+            setCredentialRequiredToDecrypt(false);
+        }
+        updateEncryptionPassword(credential.getStorageCryptType(), credential.getCredential());
     }
 
     /**
      * Store the hash of the *current* password in the password history list, if device policy
      * enforces password history requirement.
      */
-    private void updatePasswordHistory(byte[] password, int userHandle) {
-        if (password == null || password.length == 0) {
-            Log.e(TAG, "checkPasswordHistory: empty password");
+    private void updatePasswordHistory(LockscreenCredential password, int userHandle) {
+        if (password.isNone()) {
+            return;
+        }
+        if (password.isPattern()) {
+            // Do not keep track of historical patterns
             return;
         }
         // Add the password to the password history. We assume all
@@ -1085,10 +853,10 @@
             passwordHistory = "";
         } else {
             final byte[] hashFactor = getPasswordHistoryHashFactor(password, userHandle);
-            String hash = passwordToHistoryHash(password, hashFactor, userHandle);
+            String hash = passwordToHistoryHash(password.getCredential(), hashFactor, userHandle);
             if (hash == null) {
                 Log.e(TAG, "Compute new style password hash failed, fallback to legacy style");
-                hash = legacyPasswordToHash(password, userHandle);
+                hash = legacyPasswordToHash(password.getCredential(), userHandle);
             }
             if (TextUtils.isEmpty(passwordHistory)) {
                 passwordHistory = hash;
@@ -1132,8 +900,8 @@
     }
 
     /**
-     * Retrieves the quality mode for {@param userHandle}.
-     * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
+     * Retrieves the quality mode for {@code userHandle}.
+     * @see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)
      *
      * @return stored password quality
      */
@@ -1147,37 +915,37 @@
     }
 
     /**
-     * Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op
+     * Enables/disables the Separate Profile Challenge for this {@code userHandle}. This is a no-op
      * for user handles that do not belong to a managed profile.
      *
      * @param userHandle Managed profile user id
      * @param enabled True if separate challenge is enabled
-     * @param managedUserPassword Managed profile previous password. Null when {@param enabled} is
+     * @param managedUserPassword Managed profile previous password. Null when {@code enabled} is
      *            true
      */
     public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled,
-            byte[] managedUserPassword) {
+            LockscreenCredential managedUserPassword) {
         if (!isManagedProfile(userHandle)) {
             return;
         }
         try {
             getLockSettings().setSeparateProfileChallengeEnabled(userHandle, enabled,
-                    managedUserPassword);
-            onAfterChangingPassword(userHandle);
+                    managedUserPassword.getCredential());
+            reportEnabledTrustAgentsChanged(userHandle);
         } catch (RemoteException e) {
             Log.e(TAG, "Couldn't update work profile challenge enabled");
         }
     }
 
     /**
-     * Returns true if {@param userHandle} is a managed profile with separate challenge.
+     * Returns true if {@code userHandle} is a managed profile with separate challenge.
      */
     public boolean isSeparateProfileChallengeEnabled(int userHandle) {
         return isManagedProfile(userHandle) && hasSeparateChallenge(userHandle);
     }
 
     /**
-     * Returns true if {@param userHandle} is a managed profile with unified challenge.
+     * Returns true if {@code userHandle} is a managed profile with unified challenge.
      */
     public boolean isManagedProfileWithUnifiedChallenge(int userHandle) {
         return isManagedProfile(userHandle) && !hasSeparateChallenge(userHandle);
@@ -1218,20 +986,6 @@
 
     /**
      * Deserialize a pattern.
-     * @param string The pattern serialized with {@link #patternToString}
-     * @return The pattern.
-     * @deprecated Pass patterns as byte[] and use byteArrayToPattern
-     */
-    @Deprecated
-    public static List<LockPatternView.Cell> stringToPattern(String string) {
-        if (string == null) {
-            return null;
-        }
-        return byteArrayToPattern(string.getBytes());
-    }
-
-    /**
-     * Deserialize a pattern.
      * @param  bytes The pattern serialized with {@link #patternToByteArray}
      * @return The pattern.
      */
@@ -1252,19 +1006,6 @@
     /**
      * Serialize a pattern.
      * @param pattern The pattern.
-     * @return The pattern in string form.
-     * @deprecated Use patternToByteArray instead.
-     */
-    @UnsupportedAppUsage
-    @Deprecated
-    public static String patternToString(List<LockPatternView.Cell> pattern) {
-        return new String(patternToByteArray(pattern));
-    }
-
-
-    /**
-     * Serialize a pattern.
-     * @param pattern The pattern.
      * @return The pattern in byte array form.
      */
     public static byte[] patternToByteArray(List<LockPatternView.Cell> pattern) {
@@ -1281,34 +1022,6 @@
         return res;
     }
 
-    /*
-     * Generate an SHA-1 hash for the pattern. Not the most secure, but it is
-     * at least a second level of protection. First level is that the file
-     * is in a location only readable by the system process.
-     * @param pattern the gesture pattern.
-     * @return the hash of the pattern in a byte array.
-     */
-    @UnsupportedAppUsage
-    public static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
-        if (pattern == null) {
-            return null;
-        }
-
-        final int patternSize = pattern.size();
-        byte[] res = new byte[patternSize];
-        for (int i = 0; i < patternSize; i++) {
-            LockPatternView.Cell cell = pattern.get(i);
-            res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
-        }
-        try {
-            MessageDigest md = MessageDigest.getInstance("SHA-1");
-            byte[] hash = md.digest(res);
-            return hash;
-        } catch (NoSuchAlgorithmException nsa) {
-            return res;
-        }
-    }
-
     private String getSalt(int userId) {
         long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0, userId);
         if (salt == 0) {
@@ -1332,6 +1045,7 @@
      * @param password the gesture pattern.
      *
      * @return the hash of the pattern in a byte array.
+     * TODO: move to LockscreenCredential class
      */
     public String legacyPasswordToHash(byte[] password, int userId) {
         if (password == null || password.length == 0) {
@@ -1362,6 +1076,7 @@
 
     /**
      * Hash the password for password history check purpose.
+     * TODO: move to LockscreenCredential class
      */
     private String passwordToHistoryHash(byte[] passwordToHash, byte[] hashFactor, int userId) {
         if (passwordToHash == null || passwordToHash.length == 0 || hashFactor == null) {
@@ -1629,7 +1344,7 @@
     }
 
     /**
-     * Disable trust until credentials have been entered for user {@param userId}.
+     * Disable trust until credentials have been entered for user {@code userId}.
      *
      * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
      *
@@ -1640,7 +1355,7 @@
     }
 
     /**
-     * Requests strong authentication for user {@param userId}.
+     * Requests strong authentication for user {@code userId}.
      *
      * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
      *
@@ -1657,7 +1372,7 @@
         }
     }
 
-    private void onAfterChangingPassword(int userHandle) {
+    private void reportEnabledTrustAgentsChanged(int userHandle) {
         getTrustManager().reportEnabledTrustAgentsChanged(userHandle);
     }
 
@@ -1823,54 +1538,36 @@
      * <p>This method is only available to code running in the system server process itself.
      *
      * @param credential The new credential to be set
-     * @param type Credential type: password / pattern / none.
-     * @param requestedQuality the requested password quality by DevicePolicyManager.
-     *        See {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
      * @param tokenHandle Handle of the escrow token
      * @param token Escrow token
-     * @param userId The user who's lock credential to be changed
+     * @param userHandle The user who's lock credential to be changed
      * @return {@code true} if the operation is successful.
      */
-    public boolean setLockCredentialWithToken(byte[] credential, int type, int requestedQuality,
-            long tokenHandle, byte[] token, int userId) {
+    public boolean setLockCredentialWithToken(LockscreenCredential credential, long tokenHandle,
+            byte[] token, int userHandle) {
         if (!hasSecureLockScreen()) {
             throw new UnsupportedOperationException(
                     "This operation requires the lock screen feature.");
         }
+        credential.checkLength();
         LockSettingsInternal localService = getLockSettingsInternal();
-        if (type != CREDENTIAL_TYPE_NONE) {
-            if (credential == null || credential.length < MIN_LOCK_PASSWORD_SIZE) {
-                throw new IllegalArgumentException("password must not be null and at least "
-                        + "of length " + MIN_LOCK_PASSWORD_SIZE);
-            }
-            final int quality = PasswordMetrics.computeForCredential(type, credential).quality;
-            final int keyguardQuality = computeKeyguardQuality(type, quality, requestedQuality);
-            if (!localService.setLockCredentialWithToken(credential, type, tokenHandle, token,
-                    keyguardQuality, userId)) {
+
+        final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
+        setKeyguardStoredPasswordQuality(credential.getQuality(), userHandle);
+
+        try {
+            if (!localService.setLockCredentialWithToken(credential.getCredential(),
+                    credential.getType(),
+                    tokenHandle, token, credential.getType(), userHandle)) {
+                setKeyguardStoredPasswordQuality(currentQuality, userHandle);
                 return false;
             }
-            setKeyguardStoredPasswordQuality(quality, userId);
-
-            updateEncryptionPasswordIfNeeded(credential, quality, userId);
-            updatePasswordHistory(credential, userId);
-            onAfterChangingPassword(userId);
-        } else {
-            if (!(credential == null || credential.length == 0)) {
-                throw new IllegalArgumentException("password must be emtpy for NONE type");
-            }
-            if (!localService.setLockCredentialWithToken(null, CREDENTIAL_TYPE_NONE, tokenHandle,
-                    token, PASSWORD_QUALITY_UNSPECIFIED, userId)) {
-                return false;
-            }
-            setKeyguardStoredPasswordQuality(PASSWORD_QUALITY_UNSPECIFIED, userId);
-
-            if (userId == UserHandle.USER_SYSTEM) {
-                // Set the encryption password to default.
-                updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
-                setCredentialRequiredToDecrypt(false);
-            }
+        } catch (RuntimeException e) {
+            setKeyguardStoredPasswordQuality(currentQuality, userHandle);
+            throw new RuntimeException("Unable to save lock credential", e);
         }
-        onAfterChangingPassword(userId);
+
+        onPostPasswordChanged(credential, userHandle);
         return true;
     }
 
@@ -1997,7 +1694,7 @@
         }
 
         /**
-         * @return true if unlocking with trust alone is allowed for {@param userId} by the current
+         * @return true if unlocking with trust alone is allowed for {@code userId} by the current
          * strong authentication requirements.
          */
         public boolean isTrustAllowedForUser(int userId) {
@@ -2005,7 +1702,7 @@
         }
 
         /**
-         * @return true if unlocking with a biometric method alone is allowed for {@param userId}
+         * @return true if unlocking with a biometric method alone is allowed for {@code userId}
          * by the current strong authentication requirements.
          */
         public boolean isBiometricAllowedForUser(int userId) {
@@ -2013,7 +1710,7 @@
         }
 
         /**
-         * Called when the strong authentication requirements for {@param userId} changed.
+         * Called when the strong authentication requirements for {@code userId} changed.
          */
         public void onStrongAuthRequiredChanged(int userId) {
         }
@@ -2102,22 +1799,4 @@
         return FRP_CREDENTIAL_ENABLED && context.getResources().getBoolean(
                 com.android.internal.R.bool.config_enableCredentialFactoryResetProtection);
     }
-
-    /**
-     * Converts a CharSequence to a byte array without requiring a toString(), which creates an
-     * additional copy.
-     *
-     * @param chars The CharSequence to convert
-     * @return A byte array representing the input
-     */
-    public static byte[] charSequenceToByteArray(CharSequence chars) {
-        if (chars == null) {
-            return null;
-        }
-        byte[] bytes = new byte[chars.length()];
-        for (int i = 0; i < chars.length(); i++) {
-            bytes[i] = (byte) chars.charAt(i);
-        }
-        return bytes;
-    }
 }
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 3f6c4d4..74a0aa3 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -1318,7 +1318,7 @@
         super.onRestoreInstanceState(ss.getSuperState());
         setPattern(
                 DisplayMode.Correct,
-                LockPatternUtils.stringToPattern(ss.getSerializedPattern()));
+                LockPatternUtils.byteArrayToPattern(ss.getSerializedPattern().getBytes()));
         mPatternDisplayMode = DisplayMode.values()[ss.getDisplayMode()];
         mInputEnabled = ss.isInputEnabled();
         mInStealthMode = ss.isInStealthMode();
diff --git a/core/java/com/android/internal/widget/LockscreenCredential.java b/core/java/com/android/internal/widget/LockscreenCredential.java
new file mode 100644
index 0000000..19e6d97
--- /dev/null
+++ b/core/java/com/android/internal/widget/LockscreenCredential.java
@@ -0,0 +1,339 @@
+/*
+ * 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.internal.widget;
+
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+
+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_PATTERN;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.storage.StorageManager;
+import android.text.TextUtils;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A class representing a lockscreen credential. It can be either an empty password, a pattern
+ * or a password (or PIN).
+ *
+ * <p> As required by some security certification, the framework tries its best to
+ * remove copies of the lockscreen credential bytes from memory. In this regard, this class
+ * abuses the {@link AutoCloseable} interface for sanitizing memory. This
+ * presents a nice syntax to auto-zeroize memory with the try-with-resource statement:
+ * <pre>
+ * try {LockscreenCredential credential = LockscreenCredential.createPassword(...) {
+ *     // Process the credential in some way
+ * }
+ * </pre>
+ * With this construct, we can garantee that there will be no copies of the password left in
+ * memory when the credential goes out of scope. This should help mitigate certain class of
+ * attacks where the attcker gains read-only access to full device memory (cold boot attack,
+ * unsecured software/hardware memory dumping interfaces such as JTAG).
+ */
+public class LockscreenCredential implements Parcelable, AutoCloseable {
+
+    private final int mType;
+    // Stores raw credential bytes, or null if credential has been zeroized. An empty password
+    // is represented as a byte array of length 0.
+    private byte[] mCredential;
+    // Store the quality of the password, this is used to distinguish between pin
+    // (PASSWORD_QUALITY_NUMERIC) and password (PASSWORD_QUALITY_ALPHABETIC).
+    private final int mQuality;
+
+    /**
+     * Private constructor, use static builder methods instead.
+     *
+     * <p> Builder methods should create a private copy of the credential bytes and pass in here.
+     * LockscreenCredential will only store the reference internally without copying. This is to
+     * minimize the number of extra copies introduced.
+     */
+    private LockscreenCredential(int type, int quality, byte[] credential) {
+        Preconditions.checkNotNull(credential);
+        if (type == CREDENTIAL_TYPE_NONE) {
+            Preconditions.checkArgument(credential.length == 0);
+        } else {
+            Preconditions.checkArgument(credential.length > 0);
+        }
+        mType = type;
+        mQuality = quality;
+        mCredential = credential;
+    }
+
+    /**
+     * Creates a LockscreenCredential object representing empty password.
+     */
+    public static LockscreenCredential createNone() {
+        return new LockscreenCredential(CREDENTIAL_TYPE_NONE, PASSWORD_QUALITY_UNSPECIFIED,
+                new byte[0]);
+    }
+
+    /**
+     * Creates a LockscreenCredential object representing the given pattern.
+     */
+    public static LockscreenCredential createPattern(@NonNull List<LockPatternView.Cell> pattern) {
+        return new LockscreenCredential(CREDENTIAL_TYPE_PATTERN,
+                PASSWORD_QUALITY_SOMETHING,
+                LockPatternUtils.patternToByteArray(pattern));
+    }
+
+    /**
+     * Creates a LockscreenCredential object representing the given alphabetic password.
+     */
+    public static LockscreenCredential createPassword(@NonNull CharSequence password) {
+        return new LockscreenCredential(CREDENTIAL_TYPE_PASSWORD,
+                PASSWORD_QUALITY_ALPHABETIC,
+                charSequenceToByteArray(password));
+    }
+
+    /**
+     * Creates a LockscreenCredential object representing the given numeric PIN.
+     */
+    public static LockscreenCredential createPin(@NonNull CharSequence pin) {
+        return new LockscreenCredential(CREDENTIAL_TYPE_PASSWORD,
+                PASSWORD_QUALITY_NUMERIC,
+                charSequenceToByteArray(pin));
+    }
+
+    /**
+     * Creates a LockscreenCredential object representing the given alphabetic password.
+     * If the supplied password is empty, create an empty credential object.
+     */
+    public static LockscreenCredential createPasswordOrNone(@Nullable CharSequence password) {
+        if (TextUtils.isEmpty(password)) {
+            return createNone();
+        } else {
+            return createPassword(password);
+        }
+    }
+
+    /**
+     * Creates a LockscreenCredential object representing the given numeric PIN.
+     * If the supplied password is empty, create an empty credential object.
+     */
+    public static LockscreenCredential createPinOrNone(@Nullable CharSequence pin) {
+        if (TextUtils.isEmpty(pin)) {
+            return createNone();
+        } else {
+            return createPin(pin);
+        }
+    }
+
+    /**
+     * Create a LockscreenCredential object based on raw credential and type
+     * TODO: Remove once LSS.setUserPasswordMetrics accepts a LockscreenCredential
+     */
+    public static LockscreenCredential createRaw(int type, byte[] credential) {
+        if (type == CREDENTIAL_TYPE_NONE) {
+            return createNone();
+        } else {
+            return new LockscreenCredential(type, PASSWORD_QUALITY_UNSPECIFIED, credential);
+        }
+    }
+
+    private void ensureNotZeroized() {
+        Preconditions.checkState(mCredential != null, "Credential is already zeroized");
+    }
+    /**
+     * Returns the type of this credential. Can be one of {@link #CREDENTIAL_TYPE_NONE},
+     * {@link #CREDENTIAL_TYPE_PATTERN} or {@link #CREDENTIAL_TYPE_PASSWORD}.
+     *
+     * TODO: Remove once credential type is internal. Callers should use {@link #isNone},
+     * {@link #isPattern} and {@link #isPassword} instead.
+     */
+    public int getType() {
+        ensureNotZeroized();
+        return mType;
+    }
+
+    /**
+     * Returns the quality type of the credential
+     */
+    public int getQuality() {
+        ensureNotZeroized();
+        return mQuality;
+    }
+
+    /**
+     * Returns the credential bytes. This is a direct reference of the internal field so
+     * callers should not modify it.
+     *
+     */
+    public byte[] getCredential() {
+        ensureNotZeroized();
+        return mCredential;
+    }
+
+    /**
+     *  Returns the credential type recognized by {@link StorageManager}. Can be one of
+     *  {@link StorageManager#CRYPT_TYPE_DEFAULT}, {@link StorageManager#CRYPT_TYPE_PATTERN},
+     *  {@link StorageManager#CRYPT_TYPE_PIN} or {@link StorageManager#CRYPT_TYPE_PASSWORD}.
+     */
+    public int getStorageCryptType() {
+        if (isNone()) {
+            return StorageManager.CRYPT_TYPE_DEFAULT;
+        }
+        if (isPattern()) {
+            return StorageManager.CRYPT_TYPE_PATTERN;
+        }
+        if (isPassword()) {
+            return mQuality == PASSWORD_QUALITY_NUMERIC
+                    ? StorageManager.CRYPT_TYPE_PIN : StorageManager.CRYPT_TYPE_PASSWORD;
+        }
+        throw new IllegalStateException("Unhandled credential type");
+    }
+
+    /** Returns whether this is an empty credential */
+    public boolean isNone() {
+        ensureNotZeroized();
+        return mType == CREDENTIAL_TYPE_NONE;
+    }
+
+    /** Returns whether this is a pattern credential */
+    public boolean isPattern() {
+        ensureNotZeroized();
+        return mType == CREDENTIAL_TYPE_PATTERN;
+    }
+
+    /** Returns whether this is a password credential */
+    public boolean isPassword() {
+        ensureNotZeroized();
+        return mType == CREDENTIAL_TYPE_PASSWORD;
+    }
+
+    /** Returns the length of the credential */
+    public int size() {
+        ensureNotZeroized();
+        return mCredential.length;
+    }
+
+    /** Create a copy of the credential */
+    public LockscreenCredential duplicate() {
+        return new LockscreenCredential(mType, mQuality,
+                mCredential != null ? Arrays.copyOf(mCredential, mCredential.length) : null);
+    }
+
+    /**
+     * Zeroize the credential bytes.
+     */
+    public void zeroize() {
+        if (mCredential != null) {
+            Arrays.fill(mCredential, (byte) 0);
+            mCredential = null;
+        }
+    }
+
+    /**
+     * Check if the credential meets minimal length requirement.
+     *
+     * @throws IllegalArgumentException if the credential is too short.
+     */
+    public void checkLength() {
+        if (isNone()) {
+            return;
+        }
+        if (isPattern()) {
+            if (size() < LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
+                throw new IllegalArgumentException("pattern must not be null and at least "
+                        + LockPatternUtils.MIN_LOCK_PATTERN_SIZE + " dots long.");
+            }
+            return;
+        }
+        if (isPassword()) {
+            if (size() < LockPatternUtils.MIN_LOCK_PASSWORD_SIZE) {
+                throw new IllegalArgumentException("password must not be null and at least "
+                        + "of length " + LockPatternUtils.MIN_LOCK_PASSWORD_SIZE);
+            }
+            return;
+        }
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mType);
+        dest.writeInt(mQuality);
+        dest.writeByteArray(mCredential);
+    }
+
+    public static final Parcelable.Creator<LockscreenCredential> CREATOR =
+            new Parcelable.Creator<LockscreenCredential>() {
+
+        @Override
+        public LockscreenCredential createFromParcel(Parcel source) {
+            return new LockscreenCredential(source.readInt(), source.readInt(),
+                    source.createByteArray());
+        }
+
+        @Override
+        public LockscreenCredential[] newArray(int size) {
+            return new LockscreenCredential[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void close() {
+        zeroize();
+    }
+
+    @Override
+    public int hashCode() {
+        // Effective Java — Item 9
+        return ((17 + mType) * 31 + mQuality) * 31 + mCredential.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) return true;
+        if (!(o instanceof LockscreenCredential)) return false;
+        final LockscreenCredential other = (LockscreenCredential) o;
+        return mType == other.mType && mQuality == other.mQuality
+                && Arrays.equals(mCredential, other.mCredential);
+    }
+
+    /**
+     * Converts a CharSequence to a byte array without requiring a toString(), which creates an
+     * additional copy.
+     *
+     * @param chars The CharSequence to convert
+     * @return A byte array representing the input
+     */
+    private static byte[] charSequenceToByteArray(CharSequence chars) {
+        if (chars == null) {
+            return new byte[0];
+        }
+        byte[] bytes = new byte[chars.length()];
+        for (int i = 0; i < chars.length(); i++) {
+            bytes[i] = (byte) chars.charAt(i);
+        }
+        return bytes;
+    }
+}
diff --git a/core/java/com/android/internal/widget/PasswordValidationError.java b/core/java/com/android/internal/widget/PasswordValidationError.java
new file mode 100644
index 0000000..41b234e
--- /dev/null
+++ b/core/java/com/android/internal/widget/PasswordValidationError.java
@@ -0,0 +1,78 @@
+/*
+ * 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.internal.widget;
+
+/**
+ * Password validation error containing an error code and optional requirement.
+ */
+public class PasswordValidationError {
+    // Password validation error codes
+    public static final int WEAK_CREDENTIAL_TYPE = 1;
+    public static final int CONTAINS_INVALID_CHARACTERS = 2;
+    public static final int TOO_SHORT = 3;
+    public static final int TOO_LONG = 4;
+    public static final int CONTAINS_SEQUENCE = 5;
+    public static final int NOT_ENOUGH_LETTERS = 6;
+    public static final int NOT_ENOUGH_UPPER_CASE = 7;
+    public static final int NOT_ENOUGH_LOWER_CASE = 8;
+    public static final int NOT_ENOUGH_DIGITS = 9;
+    public static final int NOT_ENOUGH_SYMBOLS = 10;
+    public static final int NOT_ENOUGH_NON_LETTER = 11;
+    public static final int NOT_ENOUGH_NON_DIGITS = 12;
+    public static final int RECENTLY_USED = 13;
+    // WARNING: if you add a new error, make sure it is presented to the user correctly in Settings.
+
+    public final int errorCode;
+    public final int requirement;
+
+    public PasswordValidationError(int errorCode) {
+        this(errorCode, 0);
+    }
+
+    public PasswordValidationError(int errorCode, int requirement) {
+        this.errorCode = errorCode;
+        this.requirement = requirement;
+    }
+
+    @Override
+    public String toString() {
+        return errorCodeToString(errorCode) + (requirement > 0 ? "; required: " + requirement : "");
+    }
+
+    /**
+     * Returns textual representation of the error for logging purposes.
+     */
+    private static String errorCodeToString(int error) {
+        switch (error) {
+            case WEAK_CREDENTIAL_TYPE: return "Weak credential type";
+            case CONTAINS_INVALID_CHARACTERS: return "Contains an invalid character";
+            case TOO_SHORT: return "Password too short";
+            case TOO_LONG: return "Password too long";
+            case CONTAINS_SEQUENCE: return "Sequence too long";
+            case NOT_ENOUGH_LETTERS: return "Too few letters";
+            case NOT_ENOUGH_UPPER_CASE: return "Too few upper case letters";
+            case NOT_ENOUGH_LOWER_CASE: return "Too few lower case letters";
+            case NOT_ENOUGH_DIGITS: return "Too few numeric characters";
+            case NOT_ENOUGH_SYMBOLS: return "Too few symbols";
+            case NOT_ENOUGH_NON_LETTER: return "Too few non-letter characters";
+            case NOT_ENOUGH_NON_DIGITS: return "Too few non-numeric characters";
+            case RECENTLY_USED: return "Pin or password was recently used";
+            default: return "Unknown error " + error;
+        }
+    }
+
+}
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 697825d..ea0389f 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -168,6 +168,10 @@
     // These are the permitted backup transport service components
     final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
 
+    // These are packages mapped to maps of component class name to default enabled state.
+    final ArrayMap<String, ArrayMap<String, Boolean>> mPackageComponentEnabledState =
+            new ArrayMap<>();
+
     // Package names that are exempted from private API blacklisting
     final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>();
 
@@ -301,6 +305,10 @@
         return mBackupTransportWhitelist;
     }
 
+    public ArrayMap<String, Boolean> getComponentsEnabledStates(String packageName) {
+        return mPackageComponentEnabledState.get(packageName);
+    }
+
     public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() {
         return mDisabledUntilUsedPreinstalledCarrierApps;
     }
@@ -846,6 +854,14 @@
                         }
                         XmlUtils.skipCurrentTag(parser);
                     } break;
+                    case "component-override": {
+                        if (allowAppConfigs) {
+                            readComponentOverrides(parser, permFile);
+                        } else {
+                            logNotAllowedInPartition(name, permFile, parser);
+                        }
+                        XmlUtils.skipCurrentTag(parser);
+                    } break;
                     case "backup-transport-whitelisted-service": {
                         if (allowFeatures) {
                             String serviceName = parser.getAttributeValue(null, "service");
@@ -1269,6 +1285,54 @@
         }
     }
 
+    private void readComponentOverrides(XmlPullParser parser, File permFile)
+            throws IOException, XmlPullParserException {
+        String pkgname = parser.getAttributeValue(null, "package");
+        if (pkgname == null) {
+            Slog.w(TAG, "<component-override> without package in "
+                    + permFile + " at " + parser.getPositionDescription());
+            return;
+        }
+
+        pkgname = pkgname.intern();
+
+        final int depth = parser.getDepth();
+        while (XmlUtils.nextElementWithin(parser, depth)) {
+            String name = parser.getName();
+            if ("component".equals(name)) {
+                String clsname = parser.getAttributeValue(null, "class");
+                String enabled = parser.getAttributeValue(null, "enabled");
+                if (clsname == null) {
+                    Slog.w(TAG, "<component> without class in "
+                            + permFile + " at " + parser.getPositionDescription());
+                    return;
+                } else if (enabled == null) {
+                    Slog.w(TAG, "<component> without enabled in "
+                            + permFile + " at " + parser.getPositionDescription());
+                    return;
+                }
+
+                if (clsname.startsWith(".")) {
+                    clsname = pkgname + clsname;
+                }
+
+                clsname = clsname.intern();
+
+                ArrayMap<String, Boolean> componentEnabledStates =
+                        mPackageComponentEnabledState.get(pkgname);
+                if (componentEnabledStates == null) {
+                    componentEnabledStates = new ArrayMap<>();
+                    mPackageComponentEnabledState.put(pkgname,
+                            componentEnabledStates);
+                }
+
+                componentEnabledStates.put(clsname, !"false".equals(enabled));
+            } else {
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
     private static boolean isSystemProcess() {
         return Process.myUid() == Process.SYSTEM_UID;
     }
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index ce405fe..d9428c5 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -159,7 +159,6 @@
                 "android_media_AudioVolumeGroups.cpp",
                 "android_media_AudioVolumeGroupCallback.cpp",
                 "android_media_DeviceCallback.cpp",
-                "android_media_JetPlayer.cpp",
                 "android_media_MediaMetricsJNI.cpp",
                 "android_media_MicrophoneInfo.cpp",
                 "android_media_midi.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 3497f92..4f7f18e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -95,7 +95,6 @@
 extern int register_android_media_AudioVolumeGroups(JNIEnv *env);
 extern int register_android_media_AudioVolumeGroupChangeHandler(JNIEnv *env);
 extern int register_android_media_MicrophoneInfo(JNIEnv *env);
-extern int register_android_media_JetPlayer(JNIEnv *env);
 extern int register_android_media_ToneGenerator(JNIEnv *env);
 extern int register_android_media_midi(JNIEnv *env);
 
@@ -1502,7 +1501,6 @@
     REG_JNI(register_android_media_AudioProductStrategies),
     REG_JNI(register_android_media_AudioVolumeGroups),
     REG_JNI(register_android_media_AudioVolumeGroupChangeHandler),
-    REG_JNI(register_android_media_JetPlayer),
     REG_JNI(register_android_media_MicrophoneInfo),
     REG_JNI(register_android_media_RemoteDisplay),
     REG_JNI(register_android_media_ToneGenerator),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 89c12f8..0487e13 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -9,6 +9,7 @@
 #include "SkColorSpace.h"
 #include "GraphicsJNI.h"
 #include "SkStream.h"
+#include "SkWebpEncoder.h"
 
 #include "android_os_Parcel.h"
 #include "android_util_Binder.h"
@@ -526,27 +527,14 @@
 enum JavaEncodeFormat {
     kJPEG_JavaEncodeFormat = 0,
     kPNG_JavaEncodeFormat = 1,
-    kWEBP_JavaEncodeFormat = 2
+    kWEBP_JavaEncodeFormat = 2,
+    kWEBP_LOSSY_JavaEncodeFormat = 3,
+    kWEBP_LOSSLESS_JavaEncodeFormat = 4,
 };
 
 static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
                                 jint format, jint quality,
                                 jobject jstream, jbyteArray jstorage) {
-    SkEncodedImageFormat fm;
-    switch (format) {
-    case kJPEG_JavaEncodeFormat:
-        fm = SkEncodedImageFormat::kJPEG;
-        break;
-    case kPNG_JavaEncodeFormat:
-        fm = SkEncodedImageFormat::kPNG;
-        break;
-    case kWEBP_JavaEncodeFormat:
-        fm = SkEncodedImageFormat::kWEBP;
-        break;
-    default:
-        return JNI_FALSE;
-    }
-
     LocalScopedBitmap bitmap(bitmapHandle);
     if (!bitmap.valid()) {
         return JNI_FALSE;
@@ -577,6 +565,30 @@
         }
         skbitmap = p3;
     }
+    SkEncodedImageFormat fm;
+    switch (format) {
+        case kJPEG_JavaEncodeFormat:
+            fm = SkEncodedImageFormat::kJPEG;
+            break;
+        case kPNG_JavaEncodeFormat:
+            fm = SkEncodedImageFormat::kPNG;
+            break;
+        case kWEBP_JavaEncodeFormat:
+            fm = SkEncodedImageFormat::kWEBP;
+            break;
+        case kWEBP_LOSSY_JavaEncodeFormat:
+        case kWEBP_LOSSLESS_JavaEncodeFormat: {
+            SkWebpEncoder::Options options;
+            options.fQuality = quality;
+            options.fCompression = format == kWEBP_LOSSY_JavaEncodeFormat ?
+                    SkWebpEncoder::Compression::kLossy : SkWebpEncoder::Compression::kLossless;
+            return SkWebpEncoder::Encode(strm.get(), skbitmap.pixmap(), options) ?
+                    JNI_TRUE : JNI_FALSE;
+        }
+        default:
+            return JNI_FALSE;
+    }
+
     return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
 }
 
diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp
index ec91cbf..4d907f6 100644
--- a/core/jni/android/graphics/ImageDecoder.cpp
+++ b/core/jni/android/graphics/ImageDecoder.cpp
@@ -374,16 +374,17 @@
     if (scale || jsubset) {
         int translateX = 0;
         int translateY = 0;
+        SkImageInfo scaledInfo;
         if (jsubset) {
             SkIRect subset;
             GraphicsJNI::jrect_to_irect(env, jsubset, &subset);
 
-            translateX    = -subset.fLeft;
-            translateY    = -subset.fTop;
-            desiredWidth  =  subset.width();
-            desiredHeight =  subset.height();
+            translateX = -subset.fLeft;
+            translateY = -subset.fTop;
+            scaledInfo = bitmapInfo.makeWH(subset.width(), subset.height());
+        } else {
+            scaledInfo = bitmapInfo.makeWH(desiredWidth, desiredHeight);
         }
-        SkImageInfo scaledInfo = bitmapInfo.makeWH(desiredWidth, desiredHeight);
         SkBitmap scaledBm;
         if (!scaledBm.setInfo(scaledInfo)) {
             doThrowIOE(env, "Failed scaled setInfo");
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index c7b36d0..3c0971b 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -750,9 +750,11 @@
   }
 
   // May be nullptr.
-  const DynamicRefTable* dynamic_ref_table = assetmanager->GetDynamicRefTableForCookie(cookie);
+  std::shared_ptr<const DynamicRefTable> dynamic_ref_table =
+      assetmanager->GetDynamicRefTableForCookie(cookie);
 
-  std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(dynamic_ref_table);
+  std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(
+      std::move(dynamic_ref_table));
   status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), true);
   asset.reset();
 
@@ -785,9 +787,11 @@
   ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie);
 
   // May be nullptr.
-  const DynamicRefTable* dynamic_ref_table = assetmanager->GetDynamicRefTableForCookie(cookie);
+   std::shared_ptr<const DynamicRefTable> dynamic_ref_table =
+       assetmanager->GetDynamicRefTableForCookie(cookie);
 
-  std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(dynamic_ref_table);
+  std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(
+      std::move(dynamic_ref_table));
   status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), true);
   asset.reset();
 
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index e406e22..2232393 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -992,6 +992,31 @@
     return IPCThreadState::self()->blockUntilThreadAvailable();
 }
 
+static jobject android_os_Binder_waitForService(
+        JNIEnv *env,
+        jclass /* clazzObj */,
+        jstring serviceNameObj) {
+
+    const jchar* serviceName = env->GetStringCritical(serviceNameObj, nullptr);
+    if (!serviceName) {
+        signalExceptionForError(env, nullptr, BAD_VALUE, true /*canThrowRemoteException*/);
+        return nullptr;
+    }
+    String16 nameCopy = String16(reinterpret_cast<const char16_t *>(serviceName),
+            env->GetStringLength(serviceNameObj));
+    env->ReleaseStringCritical(serviceNameObj, serviceName);
+
+    auto sm = android::defaultServiceManager();
+    sp<IBinder> service = sm->waitForService(nameCopy);
+
+    if (!service) {
+        signalExceptionForError(env, nullptr, NAME_NOT_FOUND, true /*canThrowRemoteException*/);
+        return nullptr;
+    }
+
+    return javaObjectForIBinder(env, service);
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gBinderMethods[] = {
@@ -1019,7 +1044,8 @@
     { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
     { "getNativeBBinderHolder", "()J", (void*)android_os_Binder_getNativeBBinderHolder },
     { "getNativeFinalizer", "()J", (void*)android_os_Binder_getNativeFinalizer },
-    { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }
+    { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable },
+    { "waitForService", "(Ljava/lang/String;)Landroid/os/IBinder;", (void*)android_os_Binder_waitForService }
 };
 
 const char* const kBinderPathName = "android/os/Binder";
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 0fada1b..49c5cad 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -35,7 +35,6 @@
 #include <limits>
 #include <memory>
 #include <string>
-#include <unordered_map>
 #include <vector>
 
 #include "core_jni_helpers.h"
@@ -62,45 +61,26 @@
 
 using namespace android;
 
-static const bool kDebugPolicy = false;
-static const bool kDebugProc = false;
+static constexpr bool kDebugPolicy = false;
+static constexpr bool kDebugProc = false;
 
 // Stack reservation for reading small proc files.  Most callers of
 // readProcFile() are reading files under this threshold, e.g.,
 // /proc/pid/stat.  /proc/pid/time_in_state ends up being about 520
 // bytes, so use 1024 for the stack to provide a bit of slack.
-static const ssize_t kProcReadStackBufferSize = 1024;
+static constexpr ssize_t kProcReadStackBufferSize = 1024;
 
 // The other files we read from proc tend to be a bit larger (e.g.,
 // /proc/stat is about 3kB), so once we exhaust the stack buffer,
 // retry with a relatively large heap-allocated buffer.  We double
 // this size and retry until the whole file fits.
-static const ssize_t kProcReadMinHeapBufferSize = 4096;
+static constexpr ssize_t kProcReadMinHeapBufferSize = 4096;
 
 #if GUARD_THREAD_PRIORITY
 Mutex gKeyCreateMutex;
 static pthread_key_t gBgKey = -1;
 #endif
 
-/*
- *  cpuset/sched aggregate profile mappings
- */
-static const std::unordered_map<int, std::string> kCpusetProfileMap = {
-    {SP_DEFAULT, "CPUSET_SP_DEFAULT"}, {SP_BACKGROUND, "CPUSET_SP_BACKGROUND"},
-    {SP_FOREGROUND, "CPUSET_SP_FOREGROUND"},{SP_SYSTEM, "CPUSET_SP_SYSTEM"},
-    {SP_AUDIO_APP, "CPUSET_SP_FOREGROUND"}, {SP_AUDIO_SYS, "CPUSET_SP_FOREGROUND"},
-    {SP_TOP_APP, "CPUSET_SP_TOP_APP"}, {SP_RT_APP, "CPUSET_SP_DEFAULT"},
-    {SP_RESTRICTED, "CPUSET_SP_RESTRICTED"}
-};
-
-static const std::unordered_map<int, std::string> kSchedProfileMap = {
-    {SP_DEFAULT, "SCHED_SP_DEFAULT"}, {SP_BACKGROUND, "SCHED_SP_BACKGROUND"},
-    {SP_FOREGROUND, "SCHED_SP_FOREGROUND"}, {SP_SYSTEM, "SCHED_SP_DEFAULT"},
-    {SP_AUDIO_APP, "SCHED_SP_FOREGROUND"}, {SP_AUDIO_SYS, "SCHED_SP_FOREGROUND"},
-    {SP_TOP_APP, "SCHED_SP_TOP_APP"}, {SP_RT_APP, "SCHED_SP_RT_APP"},
-    {SP_RESTRICTED, "SCHED_SP_DEFAULT"}
-};
-
 // For both of these, err should be in the errno range (positive), not a status_t (negative)
 static void signalExceptionForError(JNIEnv* env, int err, int tid) {
     switch (err) {
@@ -227,7 +207,7 @@
         return;
     }
 
-    int res = SetTaskProfiles(tid, {kSchedProfileMap.at(grp)}, true) ? 0 : -1;
+    int res = SetTaskProfiles(tid, {get_sched_policy_name((SchedPolicy)grp)}, true) ? 0 : -1;
 
     if (res != NO_ERROR) {
         signalExceptionForGroupError(env, -res, tid);
@@ -241,7 +221,7 @@
         return;
     }
 
-    int res = SetTaskProfiles(tid, {kCpusetProfileMap.at(grp)}, true) ? 0 : -1;
+    int res = SetTaskProfiles(tid, {get_cpuset_policy_profile_name((SchedPolicy)grp)}, true) ? 0 : -1;
 
     if (res != NO_ERROR) {
         signalExceptionForGroupError(env, -res, tid);
@@ -328,7 +308,7 @@
             if (t_pri >= ANDROID_PRIORITY_BACKGROUND) {
                 // This task wants to stay at background
                 // update its cpuset so it doesn't only run on bg core(s)
-                err = SetTaskProfiles(t_pid, {kCpusetProfileMap.at(grp)}, true) ? 0 : -1;
+                err = SetTaskProfiles(t_pid, {get_cpuset_policy_profile_name((SchedPolicy)grp)}, true) ? 0 : -1;
                 if (err != NO_ERROR) {
                     signalExceptionForGroupError(env, -err, t_pid);
                     break;
@@ -337,7 +317,7 @@
             }
         }
 
-        err = SetTaskProfiles(t_pid, {kCpusetProfileMap.at(grp)}, true) ? 0 : -1;
+        err = SetTaskProfiles(t_pid, {get_cpuset_policy_profile_name((SchedPolicy)grp)}, true) ? 0 : -1;
         if (err != NO_ERROR) {
             signalExceptionForGroupError(env, -err, t_pid);
             break;
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index af34e7b7..bf1cea8 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -112,7 +112,9 @@
 }
 
 static jobject android_view_InputChannel_createInputChannel(JNIEnv* env,
-        std::unique_ptr<NativeInputChannel> nativeInputChannel) {
+        sp<InputChannel> inputChannel) {
+    std::unique_ptr<NativeInputChannel> nativeInputChannel =
+            std::make_unique<NativeInputChannel>(inputChannel);
     jobject inputChannelObj = env->NewObject(gInputChannelClassInfo.clazz,
             gInputChannelClassInfo.ctor);
     if (inputChannelObj) {
@@ -143,14 +145,12 @@
         return nullptr;
     }
 
-    jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
-            std::make_unique<NativeInputChannel>(serverChannel));
+    jobject serverChannelObj = android_view_InputChannel_createInputChannel(env, serverChannel);
     if (env->ExceptionCheck()) {
         return nullptr;
     }
 
-    jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
-            std::make_unique<NativeInputChannel>(clientChannel));
+    jobject clientChannelObj = android_view_InputChannel_createInputChannel(env, clientChannel);
     if (env->ExceptionCheck()) {
         return nullptr;
     }
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index b8c5270..94be61f 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2412,4 +2412,18 @@
     // OS: R
     SETTINGS_WIFI_CONFIGURE_NETWORK = 1800;
 
+    // OPEN: Settings > Accessibility > Magnification
+    // CATEGORY: SETTINGS
+    // OS: R
+    // Note: Shows up only when Magnify with shortcut is enabled
+    // and under accessibility button mode.
+    DIALOG_TOGGLE_SCREEN_MAGNIFICATION_ACCESSIBILITY_BUTTON = 1801;
+
+    // OPEN: Settings > Accessibility > Magnification
+    // CATEGORY: SETTINGS
+    // OS: R
+    // Note: Shows up only when Magnify with shortcut is enabled.
+    // and under gesture navigation mode.
+    DIALOG_TOGGLE_SCREEN_MAGNIFICATION_GESTURE_NAVIGATION = 1802;
+
 }
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 15b98af..06040a5 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -43,7 +43,7 @@
     reserved 15; // next_heartbeat
     reserved 16; // last_heartbeat_time_millis
     reserved 17; // next_heartbeat_time_millis
-    optional bool in_parole = 18;
+    reserved 18; // in_parole
     optional bool in_thermal = 19;
 
     repeated int32 started_users = 2;
@@ -534,7 +534,7 @@
         option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
         optional bool is_charging = 1;
-        optional bool is_in_parole = 2;
+        reserved 2; // is_in_parole
         optional int64 elapsed_realtime = 6;
 
         // List of UIDs currently in the foreground.
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto
index 301fa13..d010c8f 100644
--- a/core/proto/android/service/package.proto
+++ b/core/proto/android/service/package.proto
@@ -114,6 +114,13 @@
         optional int32 distraction_flags = 10;
     }
 
+    message InstallSourceProto {
+        option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+        // The package that requested the installation of this one.
+        optional string initiating_package_name = 1;
+    }
+
     // Name of package. e.g. "com.android.providers.telephony".
     optional string name = 1;
     // UID for this package as assigned by Android OS.
@@ -133,4 +140,6 @@
     repeated SplitProto splits = 8;
     // Per-user package info.
     repeated UserInfoProto users = 9;
+    // Where the request to install this package came from,
+    optional InstallSourceProto install_source = 10;
 }
diff --git a/core/proto/android/service/procstats.proto b/core/proto/android/service/procstats.proto
index f49a044..ad7299d 100644
--- a/core/proto/android/service/procstats.proto
+++ b/core/proto/android/service/procstats.proto
@@ -241,12 +241,25 @@
     repeated StateStats active_state_stats = 6;
 }
 
-// Next Tag: 3
+// Next Tag: 7
 message PackageAssociationProcessStatsProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     // Name of the target component.
     optional string component_name = 1;
+
+    // Total count of the times this association appeared.
+    optional int32 total_count = 3;
+
+    // Millisecond uptime total duration this association was around.
+    optional int64 total_duration_ms = 4;
+
+    // Total count of the times this association became actively impacting its target process.
+    optional int32 active_count = 5;
+
+    // Millisecond uptime total duration this association was around.
+    optional int64 active_duration_ms = 6;
+
     // Information on one source in this association.
     repeated PackageAssociationSourceProcessStatsProto sources = 2;
 }
diff --git a/core/proto/android/stats/devicepolicy/device_policy_enums.proto b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
index 0821d14..15813a1 100644
--- a/core/proto/android/stats/devicepolicy/device_policy_enums.proto
+++ b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
@@ -113,9 +113,9 @@
   PROVISIONING_PREPROVISIONING_ACTIVITY_TIME_MS = 87;
   PROVISIONING_ENCRYPT_DEVICE_ACTIVITY_TIME_MS = 88;
   PROVISIONING_WEB_ACTIVITY_TIME_MS = 89;
-  PROVISIONING_TRAMPOLINE_ACTIVITY_TIME_MS = 90;
-  PROVISIONING_POST_ENCRYPTION_ACTIVITY_TIME_MS = 91;
-  PROVISIONING_FINALIZATION_ACTIVITY_TIME_MS = 92;
+  PROVISIONING_TRAMPOLINE_ACTIVITY_TIME_MS = 90 [deprecated=true];
+  PROVISIONING_POST_ENCRYPTION_ACTIVITY_TIME_MS = 91 [deprecated=true];
+  PROVISIONING_FINALIZATION_ACTIVITY_TIME_MS = 92 [deprecated=true];
   PROVISIONING_NETWORK_TYPE = 93;
   PROVISIONING_ACTION = 94;
   PROVISIONING_EXTRAS = 95;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b030b33..bd30699 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1624,7 +1624,7 @@
          @hide This should only be used by Settings and SystemUI.
     -->
     <permission android:name="android.permission.NETWORK_SETTINGS"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|telephony" />
 
     <!-- Allows SetupWizard to call methods in Networking services
          <p>Not for use by any other third-party or privileged applications.
@@ -2138,12 +2138,12 @@
 
     <!-- Must be required by a telephony data service to ensure that only the
          system can bind to it.
-         <p>Protection level: signature
+         <p>Protection level: signature|telephony
          @SystemApi
          @hide
     -->
     <permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|telephony" />
 
     <!-- Must be required by a NetworkService to ensure that only the
          system can bind to it.
@@ -2164,11 +2164,11 @@
 
     <!-- @SystemApi Must be required by an EuiccService to ensure that only the system can bind to
          it.
-         <p>Protection level: signature
+         <p>Protection level: signature|telephony
          @hide
     -->
     <permission android:name="android.permission.BIND_EUICC_SERVICE"
-                android:protectionLevel="signature" />
+                android:protectionLevel="signature|telephony" />
 
     <!-- ================================== -->
     <!-- Permissions for sdcard interaction -->
@@ -2955,7 +2955,7 @@
          @hide
     -->
     <permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|telephony|wifi" />
 
     <!-- @SystemApi Allows an application to use
          {@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}
@@ -3511,6 +3511,13 @@
     <permission android:name="android.permission.GET_RUNTIME_PERMISSIONS"
                 android:protectionLevel="signature" />
 
+    <!-- @SystemApi Allows the system to restore runtime permission state. This might grant
+    permissions, hence this is a more scoped, less powerful variant of GRANT_RUNTIME_PERMISSIONS.
+    Among other restrictions this cannot override user choices.
+    @hide -->
+    <permission android:name="android.permission.RESTORE_RUNTIME_PERMISSIONS"
+                android:protectionLevel="signature" />
+
     <!-- @SystemApi Allows an application to change policy_fixed permissions.
     @hide -->
     <permission android:name="android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY"
@@ -3740,7 +3747,7 @@
         @hide
     -->
    <permission android:name="android.permission.DEVICE_POWER"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|telephony" />
 
     <!-- Allows toggling battery saver on the system.
          Superseded by DEVICE_POWER permission. @hide @SystemApi
@@ -3775,13 +3782,13 @@
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.BROADCAST_SMS"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|telephony" />
 
     <!-- Allows an application to broadcast a WAP PUSH receipt notification.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.BROADCAST_WAP_PUSH"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|telephony" />
 
     <!-- @SystemApi Allows an application to broadcast privileged networking requests.
          <p>Not for use by third-party applications.
@@ -4396,13 +4403,13 @@
          {@link android.provider.BlockedNumberContract}.
          @hide -->
     <permission android:name="android.permission.READ_BLOCKED_NUMBERS"
-                android:protectionLevel="signature" />
+                android:protectionLevel="signature|telephony" />
 
     <!-- Allows the holder to write blocked numbers. See
          {@link android.provider.BlockedNumberContract}.
          @hide -->
     <permission android:name="android.permission.WRITE_BLOCKED_NUMBERS"
-                android:protectionLevel="signature" />
+                android:protectionLevel="signature|telephony" />
 
     <!-- Must be required by an {@link android.service.vr.VrListenerService}, to ensure that only
          the system can bind to it.
@@ -4944,6 +4951,14 @@
             </intent-filter>
         </receiver>
 
+        <receiver android:name="com.android.server.updates.EmergencyNumberDbInstallReceiver"
+                  android:permission="android.permission.UPDATE_CONFIG">
+            <intent-filter>
+                <action android:name="android.os.action.UPDATE_EMERGENCY_NUMBER_DB" />
+                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+            </intent-filter>
+        </receiver>
+
         <receiver android:name="com.android.server.MasterClearReceiver"
             android:permission="android.permission.MASTER_CLEAR">
             <intent-filter
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index dd9eafe..4ca0df4 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -295,7 +295,7 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om SMS\'e te stuur en te bekyk?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Berging"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"toegang te verkry tot foto\'s, media en lêers op jou toestel"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot jou foto\'s, media en lêers op jou toestel?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"Gee vir &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot jou foto\'s, media en lêers op jou toestel?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofoon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"oudio op te neem"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om oudio op te neem?"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Laat die program toe om SMS-boodskappe te ontvang en te verwerk. Dit beteken dat die program boodskappe wat na jou toestel gestuur is, kan monitor of uitvee, sonder dat jy dit gesien het."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ontvang teksboodskappe (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Laat die program toe om MMS-boodskappe te ontvang en te verwerk. Dit beteken dat die program boodskappe wat na jou toestel gestuur is kan monitor of uitvee, sonder dat jy dit gesien het."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Stuur seluitsendingboodskappe aan"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Laat die program toe om die seluitsendingmodule te bind om seluitsendingboodskappe aan te stuur wanneer hulle ontvang word. Seluitsendingwaarskuwings word in sommige liggings gelewer om jou oor noodsituasies te waarsku. Kwaadwillige programme kan met die werkverrigting of werking van jou toestel inmeng wanneer \'n noodseluitsending ontvang word."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lees seluitsending-boodskappe"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Laat die program toe om seluitsending-boodskappe te lees wat deur jou toestel ontvang word. Seluitsending-waarskuwings word in sommige plekke afgelewer om jou van noodsituasies te waarsku. Kwaadwillige programme mag inmeng met die prestasie of die werking van jou toestel wanneer \'n noodgeval se seluitsending ontvang word."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lees ingetekende nuus"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Laat die program toe om Moenie Steur Nie-opstelling te lees en skryf."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"begin kyk van toestemminggebruik"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Laat die houer toe om die toestemminggebruik vir \'n program te begin. Behoort nooit vir normale programme nodig te wees nie."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"toeganklikheidkortpadteiken"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Laat \'n program toe om die toeganklikheidkortpadteiken te definieer."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Stel wagwoordreëls"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Beheer die lengte en die karakters wat in skermslotwagwoorde en -PIN\'e toegelaat word."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitor pogings om skerm te ontsluit"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index a007c9d..eb5265e 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"መተግበሪያው የኤስ.ኤም.ኤስ. መልዕክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ማለት መተግበሪያው ወደ መሳሪያህ የተላኩ መልዕክቶችን ላንተ ሳያሳይህ ሊቆጣጠር ወይም ሊሰርዝ ይችላል።"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"የፅሁፍ መልዕክቶችን ተቀበል (ኤም.ኤም.ኤስ.)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"መተግበሪያው የኤም.ኤም.ኤስ. መልዕክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ማለት መተግበሪያው ወደ መሳሪያህ የተላኩ መልዕክቶችን ላንተ ሳያሳይህ ሊቆጣጠር ወይም ሊሰርዝ ይችላል።"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"የሕዋስ ስርጭት መልዕክቶችን ማስተላለፍ"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"የሕዋስ ስርጭት መልዕክቶች እንደመጡ ለማስተላለፍ መተግበሪያው ከሕዋስ ስርጭት ሞዱሉ ጋር እንዲተሳሰር ያስችለዋል። የሕዋስ ስርጭት ማንቂያዎች አስቸኳይ ሁኔታዎች ሲያጋጥሙ አንዳንድ አካባቢዎች ላይ የሚላኩ ናቸው። የሕዋስ ስርጭት ሲደርስ ተንኮል-አዘል መተግበሪያዎች በመሣሪያዎ አፈጻጸም ወይም አሰራር ላይ ጣልቃ ሊገቡ ይችላሉ።"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"የህዋስ ስርጭት መልዕክቶችን አንብብ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"መሣሪያህ የህዋስ ስርጭት መልዕክቶች ሲቀበል መተግበሪያው እንዲያነበው ይፈቅድለታል። የህዋስ ስርጭት ማንቂያዎች አስቸኳይ ሁኔታዎች ሲያጋጥሙ አንዳንድ አካባቢዎች ላይ የሚላኩ ናቸው። የህዋስ ስርጭት ሲደርስ ተንኮል አዘል መተግበሪያዎች በመሣሪያህ አፈጻጸም ወይም አሰራር ላይ ጣልቃ ሊገቡ ይችላሉ።"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"የምዝገባ መግቦች አንበብ"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"መተግበሪያው የአትረብሽ ውቅረትን እንዲያነብብ እና እንዲጸፍ ይፈቅዳል።"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"የእይታ ፈቃድ መጠቀምን መጀመር"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ያዢው ለአንድ መተግበሪያ የፈቃድ አጠቃቀሙን እንዲያስጀምር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ ሊያስፈልግ አይገባም።"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"የተደራሽነት አቋራጭ ዒላማ"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"መተግበሪያ የተደራሽነት አቋራጭ ዒላማን ለመግለጽ እንዲችል ይፈቅድለታል።"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"የይለፍ ቃል ደንቦች አዘጋጅ"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"በማያ ገጽ መቆለፊያ የይለፍ ቃሎች እና ፒኖች ውስጥ የሚፈቀዱ ቁምፊዎችን እና ርዝመታቸውን ተቆጣጠር።"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"የማሳያ-ክፈት ሙከራዎችን ክትትል ያድርጉባቸው"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 2e272ee..c9067e5 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -356,10 +356,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"‏للسماح للتطبيق بتلقي ومعالجة الرسائل القصيرة SMS. وهذا يعني أنه يمكن للتطبيق مراقبة الرسائل التي يتم إرسالها إلى جهازك أو حذفها بدون عرضها لك."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"تلقي رسائل نصية (رسائل وسائط متعددة)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"للسماح للتطبيق بتلقي ومعالجة رسائل الوسائط المتعددة. وهذا يعني أنه يمكن للتطبيق مراقبة الرسائل التي يتم إرسالها لجهازك أو حذفها بدون عرضها لك."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"إعادة توجيه رسائل البث الخلوي"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"يسمح للتطبيق بالارتباط بوحدة البث الخلوي لإعادة توجيه رسائل البث الخلوي بينما يتم استقبالها. ويتم تسليم تنبيهات البث الخلوي في بعض المواقع لتحذيرك في حالات الطوارئ. ويمكن أن تؤثر التطبيقات الضارة على أداء الجهاز أو تشغيله عندما يتم تلقي بث خلوي في حالات الطوارئ."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"قراءة رسائل بث الخلية"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"السماح للتطبيق بقراءة رسائل بث الخلية التي يتلقاها هذا الجهاز. يتم تسليم اشعارات بث الخلية في بعض المواقع لتحذيرك من حالات طارئة. يمكن أن تتداخل التطبيقات الضارة مع أداء أو تشغيل الجهاز عندما يتم تلقي بث خلية طارئ."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"قراءة الخلاصات المشتركة"</string>
@@ -530,7 +528,7 @@
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"للسماح للتطبيق باستخدام الأجهزة البيومترية للمصادقة"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"لإدارة أجهزة بصمة الإصبع"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"للسماح للتطبيق باستدعاء طرق لإضافة نماذج من بصمات الأصابع وحذفها."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"لاستخدام أجهزة بصمة الإصبع"</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"استخدام أجهزة بصمة الإصبع"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"للسماح للتطبيق باستخدام أجهزة بصمة الإصبع للمصادقة"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"تعديل مجموعتك الموسيقية"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"للسماح للتطبيق بتعديل مجموعتك الموسيقية."</string>
@@ -671,8 +669,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"للسماح للتطبيق بقراءة تهيئة \"عدم الإزعاج\" وكتابتها."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"بدء استخدام إذن العرض"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"للسماح للمالك ببدء استخدام الإذن لأحد التطبيقات. ولن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"هدف اختصار أدوات تمكين الوصول"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"للسماح للتطبيق بتحديد هدف اختصار أدوات تمكين الوصول."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تعيين قواعد كلمة المرور"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"للتحكم في الطول والأحرف المسموح بها في كلمات المرور وأرقام التعريف الشخصي في قفل الشاشة."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"مراقبة محاولات إلغاء قفل الشاشة"</string>
@@ -1679,8 +1675,8 @@
     <string name="expires_on" msgid="3676242949915959821">"تنتهي الصلاحية في:"</string>
     <string name="serial_number" msgid="758814067660862493">"الرقم المسلسل:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"بصمات الأصابع:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"‏بصمة أصبع SHA-256:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"‏بصمة أصبع SHA-1:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"‏بصمة إصبع SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"‏بصمة إصبع SHA-1:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"عرض الكل"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"اختيار نشاط"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"مشاركة مع"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 70d9713..7a89b65 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"এপটোক এছএমএছ বাৰ্তাবোৰ পাবলৈ আৰু প্ৰক্ৰিয়া সম্পন্ন কৰিবলৈ অনুমতি দিয়ে৷ ইয়াৰ অৰ্থ এইটোৱেই যে এপটোৱে আপোনাক বাৰ্তাবোৰ নেদেখুৱাকৈয়ে আপোনাৰ ডিভাইচলৈ পঠিওৱা বাৰ্তাবোৰ নিৰীক্ষণ কৰিব বা মচিব পাৰে৷"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"পাঠ বার্তা (এমএমএছ) বোৰ লাভ কৰক"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"এমএমএছ বার্তাবোৰ লাভ আৰু ইয়াৰ প্ৰক্ৰিয়া সম্পন্ন কৰিবলৈ এপক অনুমতি দিয়ে। ইয়াৰ অৰ্থ হৈছে এই এপে আপোনাৰ ডিভাইচলৈ প্ৰেৰণ কৰা বার্তাসমূহ আপোনাক নেদেখুৱাকৈয়ে পৰ্যবেক্ষণ আৰু মচিব পাৰে।"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"চেল সম্প্ৰচাৰ বাৰ্তাসমূহ ফৰৱাৰ্ড কৰক"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"চেল সম্প্ৰচাৰ বাৰ্তাসমূহ লাভ কৰিলে সেইবোৰ ফৰৱাৰ্ড কৰিবলৈ এপ্‌টোক চেল সম্প্ৰচাৰ মডিউলটোৰ সৈতে সংযুক্ত হ\'বলৈ অনুমতি দিয়ে। আপোনাক জৰুৰীকালীন পৰিস্থিতিসমূহৰ বিষয়ে সতৰ্ক কৰিবলৈ কিছুমান অৱস্থানত চেল সম্প্ৰচাৰ সতৰ্কবাৰ্তাসমূহ ডেলিভাৰ কৰা হয়। কোনো জৰুৰীকালীন চেল সম্প্ৰচাৰ লাভ কৰিলে ক্ষতিকাৰক এপ্‌সমূহে আপোনাৰ ডিভাইচটোৰ কাৰ্যক্ষমতা অথবা কাৰ্যপ্ৰণালীত হস্তক্ষেপ কৰিব পাৰে।"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়ক"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"আপোনাৰ ডিভাইচে লাভ কৰা চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়িবলৈ এপক অনুমতি দিয়ে। আপোনাক জৰুৰীকালীন পৰিস্থিতিবোৰত সর্তক কৰিবলৈ চেল সম্প্ৰচাৰৰ বার্তাবোৰ প্ৰেৰণ কৰা হয়। জৰুৰীকালীন চেল সম্প্ৰচাৰ লাভ কৰাৰ সময়ত আপোনাৰ ডিভাইচৰ কাৰ্যদক্ষতা বা কাৰ্যপ্ৰণালীত ক্ষতিকাৰক এপবোৰে হস্তক্ষেপ কৰিব পাৰে।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"আপুনি সদস্যভুক্ত হোৱা ফীডসমূহ পঢ়ক"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"অসুবিধা নিদিবৰ কনফিগাৰেশ্বনক পঢ়িবলৈ আৰু সালসলনি কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"চোৱাৰ অনুমতিৰ ব্যৱহাৰ আৰম্ভ কৰক"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ধাৰকক কোনো এপৰ বাবে অনুমতিৰ ব্যৱহাৰ আৰম্ভ কৰিবলৈ দিয়ে। সাধাৰণ এপ্‌সমূহৰ বাবে কেতিয়াও প্ৰয়োজন হ’ব নালাগে।"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"সাধ্য সুবিধাসমূহৰ শ্বৰ্টকাট লক্ষ্য"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"সাধ্য সুবিধাসমূহৰ শ্বৰ্টকাট লক্ষ্য নির্ধাৰণ কৰিবলৈ এটা এপক অনুমতি দিয়ে।"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"পাছৱর্ডৰ নিয়ম ছেট কৰক"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"স্ক্ৰীণ লক পাছৱৰ্ড আৰু পিনৰ দৈর্ঘ্য আৰু কি কি আখৰ ব্যৱহাৰ কৰিব পাৰে তাক নিয়ন্ত্ৰণ কৰক।"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"স্ক্ৰীণ আনলক কৰা প্ৰয়াসবোৰ পৰ্যবেক্ষণ কৰিব পাৰে"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 5d09250..21dbf03 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Tətbiqə MMS mesajlarını almaq və emal etmək icazəsi verir. Bu o deməkdir ki, tətbiq sizin mesajlarınızı sizə göstərmədən monitorinq edə və ya silə bilər."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"mətn mesajlarını qəbul edir (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Tətbiqə MMS mesajlarını qəbul və emal üçün imkan verir. Bu o deməkdir ki, bu tətbiq sizə göstərmədən cihazınıza göndərilən mesajları silə bilər."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Şəbəkə yayımı mesajlarını yönləndirin"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Tətbiqə şəbəkə yayım mesajlarını əldə edildiyi anda yönləndirmək üçün şəbəkə yayımı moduluna bağlanmaq icazəsi verir. Şəbəkə yayımı bəzi məkanlarda olan fövqəladə hadisələrlə bağlı Sizi xəbərdar etmək üçün qəbul edilir. Zərərli tətbiqlər fövqəladə şəbəkə yayımı əldə edildiyi zaman cihazın performansına və əməliyyatına müdaxilə edə bilər."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"mobil yayım mesajlarını oxuyur"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tətbiqə telefonunuz tərəfindən alınmış yayım mesajlarını oxuma icazəsi verir. Telefon yayımı bəzi məkanlarda olan fövqəladə hadisələrlə bağlı sizi xəbərdar etmək üçün qəbul edilir. Zərərli tətbiqlər təcili mobil yayım qəbul edildiyi zaman telefonunun performansına və əməliyyatına müdaxilə edə bilər."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"abunə olunmuş xəbərləri oxuyur"</string>
@@ -534,7 +532,7 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Tanınmır"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Doğrulama ləğv edildi"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Pin, nümunə və ya parol ayarlanmayıb"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Barmaq qismən müəyyən olundu. Lütfən, yenidən cəhd edin."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Barmaq izi yarımçıq müəyyən olundu. Lütfən, yenidən cəhd edin."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Barmaq izi tanınmadı. Lütfən, yenidən cəhd edin."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Barmaq izi sensoru çirklidir. Lütfən, təmizləyin və yenidən cəhd edin."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Barmağı çox tez tərpətdiniz. Yenidən edin."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Tətbiqə \"Narahat Etməyin\" konfiqurasiyasını oxumağa və yazmağa icazə verin."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"Baxış icazəsinin istifadəsinə başlayın"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Sahibinə tətbiqin icazədən istifadəsinə başlamağa imkan verir. Adi tətbiqlər üçün heç vaxt tələb edilmir."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"əlçatımlılıq qısayolunun hədəfi"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Tətbiqə əlçatımlılıq qısayolunun hədəfini müəyyən etməyə imkan verir."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Parol qaydalarını təyin edin"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ekran kilidinin parolu və PINlərində icazə verilən uzunluq və simvollara nəzarət edin."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Ekranı kiliddən çıxarmaq üçün edilən cəhdlərə nəzarət edin"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 5891bae..dbb788d 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -347,10 +347,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Dozvoljava aplikaciji da prima i obrađuje SMS poruke. To znači da aplikacija može da nadgleda ili briše poruke koje se šalju uređaju, a da vam ih ne prikaže."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"prijem tekstualnih poruka (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Dozvoljava aplikaciji da prima i obrađuje MMS poruke. To znači da aplikacija može da nadgleda ili briše poruke koje se šalju uređaju, a da vam ih ne prikaže."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Prosleđivanje poruka za mobilne uređaje na lokalitetu"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Dozvoljava aplikaciji da se vezuje za modul poruka za mobilne uređaje na lokalitetu da bi prosleđivala poruke za mobilne uređaje na lokalitetu onako kako su primljene. Obaveštenja poruka za mobilne uređaje na lokalitetu se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na učinak ili ometaju rad uređaja kada se primi poruka o hitnom slučaju za mobilne uređaje na lokalitetu."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"čitanje poruka info servisa"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Omogućava aplikaciji da čita poruke info servisa koje uređaj prima. Upozorenja info servisa se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na učinak ili ometaju funkcionisanje uređaja kada se primi poruka info servisa o hitnom slučaju."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čitanje prijavljenih fidova"</string>
@@ -662,8 +660,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Dozvoljava aplikaciji da čita i upisuje konfiguraciju podešavanja Ne uznemiravaj."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"početak korišćenja dozvole za pregled"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Dozvoljava vlasniku da započne korišćenje dozvole za aplikaciju. Nikada ne bi trebalo da bude potrebna za uobičajene aplikacije."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cilj prečice za pristupačnost"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Dozvoljava aplikaciji da definiše cilj prečice za pristupačnost."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Podešavanje pravila za lozinku"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontroliše dužinu i znakove dozvoljene u lozinkama i PIN-ovima za zaključavanje ekrana."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Nadgledajte pokušaje otključavanja ekrana"</string>
@@ -1610,8 +1606,8 @@
     <string name="expires_on" msgid="3676242949915959821">"Ističe:"</string>
     <string name="serial_number" msgid="758814067660862493">"Serijski broj:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Digitalni otisci:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 digitalni otisak:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 digitalni otisak:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 otisak prsta:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 otisak prsta:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Prikaži sve"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Izbor aktivnosti"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Deli sa"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 6fdc8f1..bae2640 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -330,7 +330,7 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Кіраваць маштабам дысплэя і пазіцыянаваннем."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Выконваць жэсты"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Можна кранаць, праводзіць пальцам, маштабаваць шчыпком, а таксама выконваць іншыя жэсты."</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Жэсты адбіткаў пальцаў"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Жэсты на сканеры адбіткаў пальцаў"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Можа распазнаваць жэсты на сканеры адбіткаў пальцаў прылады."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"адключаць ці змяняць радок стану"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Дазваляе прыкладанням адключаць радок стану або дадаваць і выдаляць сістэмныя значкі."</string>
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Дазваляе прыкладанням атрымліваць і апрацоўваць SMS-паведамленні. Гэта значыць, што прыкладанне можа кантраляваць або выдаляць паведамленні, адпраўленыя на прыладу, не паказваючы іх вам."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"атрыманне тэкставых паведамленняў (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Дазваляе прыкладанням атрымліваць і апрацоўваць MMS-паведамленнi. Гэта значыць, што прыкладанне можа кантраляваць або выдаляць паведамленні, адпраўленыя на прыладу, не паказваючы іх вам."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Пераадрасоўваць паведамленні сотавай трансляцыі"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Дазваляе праграме звязвацца з модулем сотавай трансляцыі, каб пераадрасоўваць атрыманыя там паведамленні. Абвесткі сотавай трансляцыі дасылаюцца ў некаторыя месцы, каб папярэджваць вас пра надзвычайныя сітуацыі. Шкодныя праграмы могуць негатыўна ўплываць на прадукцыйнасць або працу прылады падчас атрымання паведамленняў сотавай трансляцыі пра надзвычайныя сітуацыі."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"чытаць паведамленні базавай станцыі"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Дазваляе прыкладанню чытаць паведамленні базавай станцыі, атрыманыя прыладай. Папярэджанні базавай станцыі дасылаюцца ў некаторыя месцы, каб папярэдзіць вас аб надзвычайных сітуацыях. Шкоднасныя прыкладанні могуць уплываць на прадукцыйнасць ці працу прылады пры атрыманні паведамлення базавай станцыі аб надзвычайнай сітуацыі."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"чытаць падпісаныя каналы"</string>
@@ -540,7 +538,7 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Не распазнана"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Аўтэнтыфікацыя скасавана"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Не заданы PIN-код, узор разблакіроўкі або пароль"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Выяўлена частка адбіткаў пальцаў. Паспрабуйце яшчэ раз."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Не ўвесь адбітак пальца адсканіраваны. Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не атрымалася апрацаваць адбітак пальца. Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Датчык адбіткаў пальцаў брудны. Ачысціце яго і паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Палец рухаўся занадта хутка. Паспрабуйце яшчэ раз."</string>
@@ -551,12 +549,12 @@
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Твар распазнаны"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Твар распазнаны. Націсніце, каб пацвердзіць"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Апаратныя сродкі адбіткаў пальцаў недаступныя."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Адбіткі пальцаў нельга захаваць. Выдаліце існы адбітак."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час чакання адбіткаў пальцаў выйшаў. Паспрабуйце яшчэ раз."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Адбіткі пальцаў нельга захаваць. Выдаліце існуючы адбітак."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час чакання выйшаў. Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Аперацыя з адбіткамі пальцаў скасавана."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Аўтэнтыфікацыя па адбітках пальцаў скасавана карыстальнікам."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Занадта шмат спроб. Паспрабуйце яшчэ раз пазней."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Занадта шмат спроб. Сканер адбіткаў пальцаў адключаны."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Занадта шмат спроб. Сканер адбіткаў пальцаў выключаны."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Адбіткі пальцаў не зарэгістраваны."</string>
     <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"На гэтай прыладзе няма сканера адбіткаў пальцаў."</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Дазваляе праграме чытаць і выконваць запіс у канфігурацыю рэжыму «Не турбаваць»."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"запусціць выкарыстанне дазволаў на прагляд"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Дазваляе трымальніку запусціць выкарыстанне дазволаў праграмай. Не патрэбна для звычайных праграм."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"Аб\'екты хуткага доступу да спецыяльных магчымасцей"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Праграма зможа вызначаць аб\'екты хуткага доступу да спецыяльных магчымасцей."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Устанавіць правілы паролю"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Кіраваць даўжынёй і сімваламі, дазволенымі пры ўводзе пароляў і PIN-кодаў блакіроўкі экрана."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Сачыць за спробамі разблакіроўкі экрана"</string>
@@ -1633,7 +1629,7 @@
     <string name="expires_on" msgid="3676242949915959821">"Заканчваецца:"</string>
     <string name="serial_number" msgid="758814067660862493">"Серыйны нумар:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Адбіткі пальцаў:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"Адбітак пальцаў SHA-256:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Адбітак SHA-256:"</string>
     <string name="sha1_fingerprint" msgid="7930330235269404581">"Адбіткі пальцаў SHA-1:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Прагледзець усё"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Выберыце працэс"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index e5fb7e8..e7b3090 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Разрешава на приложението да получава и обработва SMS съобщения. Това означава, че то може да наблюдава или изтрива изпратените до устройството ви, без да ви ги покаже."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"получаване на текстови съобщения (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Разрешава на приложението да получава и обработва MMS съобщения. Това означава, че то може да наблюдава или изтрива изпратените до устройството ви, без да ви ги покаже."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Препращане на съобщения с клетъчно излъчване"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Разрешава на приложението да се обвърже с модула за клетъчно излъчване, за да препраща получените съобщения с клетъчно излъчване. Сигналите с клетъчно излъчване се получават на някои местоположения, за да ви предупредят за спешни случаи. Злонамерените приложения могат да възпрепятстват изпълнението или работата на устройството ви при получаване на такова спешно излъчване."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"четене на съобщения с клетъчно излъчване"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Разрешава на приложението да чете съобщения с клетъчно излъчване, получени от устройството ви. Сигналите с клетъчно излъчване се получават на някои местоположения, за да ви предупредят за спешни ситуации. Злонамерените приложения могат да възпрепятстват изпълнението или работата на устройството ви при получаване на такова спешно излъчване."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"четене на емисиите с абонамент"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Предоставя на приложението достъп за четене и запис до конфигурацията на „Не безпокойте“."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"стартиране на прегледа на използваните разрешения"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Разрешава на притежателя да стартира прегледа на използваните разрешения за дадено приложение. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"цел на прекия път към функцията за достъпност"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Разрешава на приложението да определя целта на прекия път към функцията за достъпност."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Задаване на правила за паролата"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Контролира дължината и разрешените знаци за паролите и ПИН кодовете за заключване на екрана."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Наблюдаване на опитите за отключване на екрана"</string>
@@ -1587,8 +1583,8 @@
     <string name="expires_on" msgid="3676242949915959821">"Изтича на:"</string>
     <string name="serial_number" msgid="758814067660862493">"Сериен номер:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Пръстови отпечатъци:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"Пръстов отпечатък SHA-256:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"Пръстов отпечатък SHA-1:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Отпечатък SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Отпечатък SHA-1:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Вижте всички"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Избор на активност"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Споделяне със:"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 651ed4d..beb08b2 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -283,7 +283,7 @@
     <string name="permgrouprequest_contacts" msgid="6032805601881764300">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার পরিচিতিতে অ্যাক্সেস দেবেন?"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"লোকেশন"</string>
     <string name="permgroupdesc_location" msgid="1346617465127855033">"এই ডিভাইসের লোকেশন অ্যাক্সেস"</string>
-    <string name="permgrouprequest_location" msgid="3788275734953323491">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে এই ডিভাইসের লোকেশন অ্যাক্সেস করতে দেবেন?"</string>
+    <string name="permgrouprequest_location" msgid="3788275734953323491">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপকে এই ডিভাইসের লোকেশন অ্যাক্সেস করতে দেবেন?"</string>
     <string name="permgrouprequestdetail_location" msgid="1347189607421252902">"আপনি এই অ্যাপ ব্যবহার করার সময়েই শুধু সেটি আপনার লোকেশন অ্যাক্সেস করতে পারবে"</string>
     <string name="permgroupbackgroundrequest_location" msgid="5039063878675613235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপকে এই ডিভাইসের লোকেশন &lt;b&gt;সব সময়&lt;/b&gt; অ্যাক্সেস করার অনুমতি দিতে চান?"</string>
     <string name="permgroupbackgroundrequestdetail_location" msgid="4597006851453417387">"আপনি যখন অ্যাপটি ব্যবহার করবেন শুধুমাত্র তখনই অ্যাপটি বর্তমান লোকেশন অ্যাক্সেস করতে পারবে।"</string>
@@ -298,7 +298,7 @@
     <string name="permgrouprequest_storage" msgid="7885942926944299560">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার ডিভাইসের ফটো, মিডিয়া এবং ফাইলে অ্যাক্সেস দেবেন?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"মাইক্রোফোন"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"অডিও রেকর্ড"</string>
-    <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে অডিও রেকর্ড করতে দেবেন?"</string>
+    <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপকে অডিও রেকর্ড করতে দেবেন?"</string>
     <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"শারীরিক অ্যাক্টিভিটি"</string>
     <string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"শারীরিক অ্যাক্টিভিটি অ্যাক্সেস করা"</string>
     <string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার শারীরিক অ্যাক্টিভিটি অ্যাক্সেস করার অনুমতি দিতে চান?"</string>
@@ -324,7 +324,7 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"প্রদর্শনের জুমের স্তর এবং লোকেশন নির্ধারন নিয়ন্ত্রণ করুন৷"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"অঙ্গভঙ্গির কাজগুলি সম্পাদন"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"আলতো চাপ দেওয়া, সোয়াইপ, পিঞ্চ করা এবং অন্যান্য ইঙ্গিতের কাজগুলি সম্পাদন করতে পারবেন৷"</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ফিঙ্গারপ্রিন্ট সেন্সরের উপর করা অঙ্গভঙ্গিগুলি"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"আঙ্গুলের ছাপ সেন্সরের উপর করা জেসচার"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ডিভাইসের আঙ্গুলের ছাপের সেন্সরের উপরে ইঙ্গিত করলে বুঝতে পারে।"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"স্ট্যাটাস বার নিষ্ক্রিয় অথবা সংশোধন করে"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"অ্যাপ্লিকেশনকে স্ট্যাটাস বার অক্ষম করতে এবং সিস্টেম আইকনগুলি সরাতে দেয়৷"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"অ্যাপ্লিকেশানটিকে এসএমএস প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো বার্তাগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"টেক্সট মেসেজ পান (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"অ্যাপ্লিকেশানটিকে MMS মেসেজ প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো মেসেজগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"সেল ব্রডকাস্টের মাধ্যমে মেসেজ ফরওয়ার্ড করুন"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"সেল ব্রডকাস্ট মেসেজ পেলে এটি সেল ব্রডকাস্ট মডিউলের সাথে তা যুক্ত করে যাতে সেই মেসেজ ফরওয়ার্ড করা যায়। আপনাকে জরুরি অবস্থা সম্পর্কে সাবধান করতে কিছু লোকেশনে সেল ব্রডকাস্ট অ্যালার্ট মেসেজ ডেলিভার করা হয়। জরুরি সেল ব্রডকাস্ট পাওয়া গেলে ক্ষতিকারক অ্যাপ আপনার ডিভাইসের পারফর্ম্যান্স ও অপারেশনে বাধা সৃষ্টি করতে পারে।"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"সেল সম্প্রচার মেসেজ পড়ুন"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"আপনার ডিভাইস দ্বারা প্রাপ্ত সেল সম্প্রচার পড়তে অ্যাপ্লিকেশানটিকে অনুমতি দেয়৷ কয়েকটি স্থানে আপনাকে জরুরি অবস্থার জন্য সতর্ক করতে জরুরি সতর্কতাগুলি বিতরণ করা হয়৷ যখন একটি জরুরি সেল সম্প্রচার প্রাপ্ত হয় তখন ক্ষতিকারক অ্যাপ্লিকেশানগুলি আপনার ডিভাইসের কার্য সম্পাদনা বা কার্যকলাপে প্রতিবন্ধকতার সৃষ্টি করতে পারে৷"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"গ্রাহক হিসেবে নেওয়া ফিডগুলি পড়ে"</string>
@@ -553,7 +551,7 @@
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"বহুবার চেষ্টা করেছেন। আঙ্গুলের ছাপ নেওয়ার সেন্সর অক্ষম করা হয়েছে।"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"আবার চেষ্টা করুন৷"</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"কোনও আঙ্গুলের ছাপ নথিভুক্ত করা হয়নি।"</string>
-    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"এই ডিভাইসে ফিঙ্গারপ্রিন্ট সেন্সর নেই।"</string>
+    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"এই ডিভাইসে আঙ্গুলের ছাপ নেওয়ার সেন্সর নেই।"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"আঙ্গুল <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"অ্যাপটিকে \'বিরক্ত করবে না\' কনফিগারেশন পড়া এবং লেখার অনুমতি দেয়।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"দেখার অনুমতি কাজে লাগানো শুরু করুন"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"কোনও অ্যাপের কোনও নির্দিষ্ট অনুমতির ব্যবহার শুরু করার ক্ষেত্রে হোল্ডারকে সাহায্য করে। সাধারণ অ্যাপের জন্য এটির পরিবর্তন হওয়ার কথা নয়।"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"অ্যাক্সেসিবিলিটির শর্টকাটের টার্গেট"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"এটি একটি অ্যাপকে অ্যাক্সেসিবিলিটির শর্টকাটের টার্গেটকে ব্যাখ্যা করতে অনুমতি দেয়।"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"পাসওয়ার্ড নিয়মগুলি সেট করে"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"স্ক্রিন লক করার পাসওয়ার্ডগুলিতে অনুমতিপ্রাপ্ত অক্ষর এবং দৈর্ঘ্য নিয়ন্ত্রণ করে৷"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"স্ক্রিন আনলক করার প্রচেষ্টাগুলির উপরে নজর রাখুন"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 0695fb8..862beee 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -347,10 +347,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Omogućava aplikaciji primanje i obradu SMS poruka. Ovo znači da aplikacija može pratiti ili brisati poruke poslane na vaš uređaj, a da vam ih pritom ne prikazuje."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"primanje tekstualnih poruka (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Omogućava aplikaciji prijem i obradu MMS poruka. Ovo znači da aplikacija može pratiti ili brisati poruke poslane na vaš uređaj, a da vam ih pritom ne prikazuje."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Prosljeđivanje poruka info servisa"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Dopušta aplikaciji da se veže za modul info servisa kako bi prosljeđivala poruke info servisa. Upozorenja koja emitira info servis se isporučuju na nekim lokacijama kako bi vas upozorila na vanredne situacije. Zlonamjerne aplikacije mogu ometati performanse ili rad vašeg uređaja kada primite informacije o vanrednoj situaciji od info servisa."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"čitanje poruka info servisa"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Omogućava aplikaciji čitanje poruka info servisa koje je primio vaš uređaj. Upozorenja koja emitira info servis se isporučuju na nekim lokacijama kako bi vas upozorila na vanredne situacije. Zlonamjerne aplikacije mogu ometati performanse ili rad vašeg uređaja kada primite informaciju o vanrednoj situaciji od info servisa."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čitanje sadržaja na koje ste pretplaćeni"</string>
@@ -519,10 +517,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Omogućava aplikaciji da sazna nivo kompleksnosti zaključavanja ekrana (visoki, srednji, niski ili bez zaključavanja), što naznačava mogući raspon trajanja i vrste zaključavanja ekrana. Aplikacija također može korisnicima predložiti da ažuriraju zaključavanje ekrana do određenog nivoa, ali korisnici slobodno mogu ignorirati prijedlog i napustiti stranicu. Važno je napomenuti da se zaključavanje ekrana ne pohranjuje kao obični tekst tako da aplikacija ne zna tačnu lozinku."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"koristi biometrijski hardver za otiske prstij"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Omogućava aplikaciji da za autentifikaciju koristi biometrijski hardver"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"upravljanje hardverom za otiske prstiju"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"upravljanje hardverom za otisak prsta"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Omogućava aplikaciji da koristi metode za dodavanje i brisanje šablona otisaka prstiju za upotrebu."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"korištenje hardvera za otiske prstiju"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Omogućava aplikaciji da za autentifikaciju koristi hardver za otiske prstiju"</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"korištenje hardvera za otisak prsta"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Omogućava aplikaciji da za autentifikaciju koristi hardver za otisak prsta"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"izmjena muzičke kolekcije"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Omogućava aplikaciji da mijenja vašu muzičku kolekciju."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"izmjena kolekcije videozapisa"</string>
@@ -550,7 +548,7 @@
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardver za otisak prsta nije dostupan."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisak prsta se ne može pohraniti. Uklonite postojeći otisak prsta."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vrijeme za prepoznavanje otiska prsta je isteklo. Pokušajte ponovo."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja sa otiskom prsta je otkazana."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja s otiskom prsta je otkazana."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Korisnik je otkazao radnju s otiskom prsta."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Previše pokušaja. Senzor za otisak prsta je onemogućen."</string>
@@ -662,8 +660,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Omogućava aplikaciji da čita i upisuje konfiguraciju načina rada Ne ometaj."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"pokrenuti korištenje odobrenja za pregled"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Dozvoljava vlasniku da pokrene korištenje odobrenja za aplikaciju. Ne bi trebalo biti potrebno za obične aplikacije."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cilj prečice pristupačnosti"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Omogućava aplikaciji da definira cilj prečice pristupačnosti."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Postavljanje pravila za lozinke"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolira dužinu i znakove koji su dozvoljeni u lozinkama za zaključavanje ekrana i PIN-ovima."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Prati pokušaje otključavanja ekrana"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 8ef9a17..28b9a16 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -154,7 +154,7 @@
     <string name="fcComplete" msgid="3118848230966886575">"Codi de funció completat."</string>
     <string name="fcError" msgid="3327560126588500777">"Problema de connexió o codi de funció no vàlid."</string>
     <string name="httpErrorOk" msgid="1191919378083472204">"D\'acord"</string>
-    <string name="httpError" msgid="7956392511146698522">"S\'ha produït un error de xarxa."</string>
+    <string name="httpError" msgid="7956392511146698522">"S\'ha produït un error de la xarxa."</string>
     <string name="httpErrorLookup" msgid="4711687456111963163">"No s\'ha pogut trobar l\'URL."</string>
     <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"L\'esquema d\'autenticació de llocs no és compatible."</string>
     <string name="httpErrorAuth" msgid="1435065629438044534">"No s\'ha pogut autenticar."</string>
@@ -324,8 +324,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controla el nivell i la posició del zoom de la pantalla."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Fer gestos"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Permet tocar, lliscar, pinçar i fer altres gestos."</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos d\'empremtes digitals"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Captura gestos realitzats en el sensor d\'empremtes digitals del dispositiu."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos d\'empremtes dactilars"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Captura gestos realitzats en el sensor d\'empremtes dactilars del dispositiu."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desactivar o modificar la barra d\'estat"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Permet que l\'aplicació desactivi la barra d\'estat o afegeixi i elimini icones del sistema."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"aparèixer a la barra d\'estat"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permet que l\'aplicació rebi i processi missatges SMS. Això vol dir que l\'aplicació pot controlar o suprimir missatges que s\'han enviat al teu dispositiu sense mostrar-te\'ls."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recepció de missatges de text (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permet que l\'aplicació rebi i processi missatges MMS. Això vol dir que l\'aplicació pot controlar o suprimir missatges que s\'han enviat al teu dispositiu sense mostrar-te\'ls."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Reenviar els missatges de difusió mòbil"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permet que l\'aplicació es vinculi al mòdul de difusió mòbil per poder reenviar els missatges de difusió mòbil a mesura que es reben. Les alertes de difusió mòbil s\'entreguen en algunes ubicacions per alertar de situacions d\'emergència. És possible que les aplicacions malicioses interfereixin en el rendiment o en el funcionament del dispositiu quan es rebi una difusió mòbil d\'emergència."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"llegir missatges de difusió mòbil"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permet que l\'aplicació llegeixi missatges de difusió mòbil rebuts pel dispositiu. Les alertes de difusió mòbil s\'entreguen en algunes ubicacions per alertar de situacions d\'emergència. És possible que les aplicacions malicioses interfereixin en el rendiment o en el funcionament del dispositiu quan es rep una difusió mòbil d\'emergència."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"llegir els feeds als quals esteu subscrit"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Permet que l\'aplicació conegui el nivell de complexitat del bloqueig de pantalla (alt, mitjà, baix o cap), que indica la llargària i el tipus de bloqueig de pantalla possibles. L\'aplicació també pot suggerir que els usuaris actualitzin el bloqueig de pantalla a un nivell determinat, però els usuaris poden ignorar aquestes recomanacions. Tingues en compte que el bloqueig de pantalla no s\'emmagatzema com a text sense format, de manera que l\'aplicació no coneix la contrasenya exacta."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"utilitza maquinari biomètric"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Permet que l\'aplicació faci servir maquinari biomètric per a l\'autenticació"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"Gestionar el maquinari d\'empremtes digitals"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permet que l\'aplicació invoqui mètodes per afegir i suprimir plantilles d\'empremtes digitals que es puguin fer servir."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"Utilitzar el maquinari d\'empremtes digitals"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permet que l\'aplicació faci servir maquinari d\'empremtes digitals per a l\'autenticació"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"Gestionar el maquinari d\'empremtes dactilars"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permet que l\'aplicació invoqui mètodes per afegir i suprimir plantilles d\'empremtes dactilars que es puguin fer servir."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"Utilitzar el maquinari d\'empremtes dactilars"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permet que l\'aplicació faci servir maquinari d\'empremtes dactilars per a l\'autenticació"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"modificar la teva col·lecció de música"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Permet que l\'aplicació modifiqui la teva col·lecció de música."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"modificar la teva col·lecció de vídeos"</string>
@@ -534,30 +532,30 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"No s\'ha reconegut"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"S\'ha cancel·lat l\'autenticació"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"No s\'ha establert cap PIN, patró o contrasenya"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"S\'ha detectat una empremta digital parcial. Torna-ho a provar."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"No s\'ha pogut processar l\'empremta digital. Torna-ho a provar."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"El sensor d\'empremtes digitals està brut. Neteja\'l i torna-ho a provar."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"S\'ha detectat una empremta dactilar parcial. Torna-ho a provar."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"No s\'ha pogut processar l\'empremta dactilar. Torna-ho a provar."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"El sensor d\'empremtes dactilars està brut. Neteja\'l i torna-ho a provar."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"El dit s\'ha mogut massa ràpid. Torna-ho a provar."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"El dit s\'ha mogut massa lentament. Torna-ho a provar."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="5309333983002526448">"L\'empremta digital s\'ha autenticat"</string>
+    <string name="fingerprint_authenticated" msgid="5309333983002526448">"L\'empremta dactilar s\'ha autenticat"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Cara autenticada"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Cara autenticada; prem el botó per confirmar"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El maquinari per a empremtes digitals no està disponible."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"L\'empremta digital no es pot desar. Suprimeix-ne una."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"S\'ha cancel·lat l\'operació d\'empremta digital."</string>
-    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"L\'usuari ha cancel·lat l\'operació d\'empremta digital."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El maquinari per a empremtes dactilars no està disponible."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"L\'empremta dactilar no es pot desar. Suprimeix-ne una."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"S\'ha esgotat el temps d\'espera per a l\'empremta dactilar. Torna-ho a provar."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"S\'ha cancel·lat l\'operació d\'empremta dactilar."</string>
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"L\'usuari ha cancel·lat l\'operació d\'empremta dactilar."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"S\'han produït massa intents. Torna-ho a provar més tard."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"S\'han fet massa intents. S\'ha desactivat el sensor d\'empremtes digitals."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"S\'han fet massa intents. S\'ha desactivat el sensor d\'empremtes dactilars."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Torna-ho a provar."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"No s\'ha registrat cap empremta digital."</string>
-    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Aquest dispositiu no té sensor d\'empremtes digitals."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Aquest dispositiu no té sensor d\'empremtes dactilars."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dit <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Icona d\'empremta digital"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Icona d\'empremta dactilar"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"gestiona el maquinari de desbloqueig facial"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"Permet que l\'aplicació afegeixi i suprimeixi plantilles de cares que es puguin fer servir."</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"utilitza el maquinari de desbloqueig facial"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permet que l\'aplicació llegeixi la configuració No molestis i hi escrigui."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"comença a utilitzar el permís de visualització"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permet que un propietari comenci a utilitzar el permís amb una aplicació. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"objectiu de la drecera d\'accessibilitat"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permet a una aplicació definir l\'objectiu de la drecera d\'accessibilitat."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir les normes de contrasenya"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Permet controlar la longitud i el nombre de caràcters permesos a les contrasenyes i als PIN del bloqueig de pantalla."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Supervisar els intents de desbloqueig de la pantalla"</string>
@@ -1165,7 +1161,7 @@
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Esborra els paràmetres predeterminats a Configuració del sistema &gt; Aplicacions &gt; Baixades."</string>
     <string name="chooseActivity" msgid="7486876147751803333">"Selecciona una acció"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Tria una aplicació per al dispositiu USB"</string>
-    <string name="noApplications" msgid="2991814273936504689">"No hi ha cap aplicació que pugui dur a terme aquesta acció."</string>
+    <string name="noApplications" msgid="2991814273936504689">"No hi ha cap aplicació que pugui fer aquesta acció."</string>
     <string name="aerr_application" msgid="250320989337856518">"S\'ha aturat <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
     <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> s\'ha aturat"</string>
     <string name="aerr_application_repeated" msgid="3146328699537439573">"L\'aplicació <xliff:g id="APPLICATION">%1$s</xliff:g> s\'atura contínuament"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 72e7a86..8ba6f34 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -234,7 +234,7 @@
     <string name="global_action_bug_report" msgid="7934010578922304799">"Hlášení chyb"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Ukončit relaci"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"Snímek obrazovky"</string>
-    <string name="bugreport_title" msgid="5981047024855257269">"Zpráva o chybě"</string>
+    <string name="bugreport_title" msgid="5981047024855257269">"Hlášení chyb"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Shromažďuje informace o aktuálním stavu zařízení. Tyto informace je následně možné poslat v e-mailové zprávě, chvíli však potrvá, než bude hlášení o chybě připraveno k odeslání. Buďte prosím trpěliví."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktivní přehled"</string>
     <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"Tato možnost se používá ve většině případů. Umožňuje sledovat průběh přehledu, zadat další podrobnosti o problému a pořizovat snímky obrazovky. Mohou být vynechány některé méně používané sekce, jejichž kontrola trvá dlouho."</string>
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Umožňuje aplikaci přijmout a zpracovat zprávy SMS. Znamená to, že aplikace může sledovat zprávy odeslané do vašeho zařízení nebo je smazat, aniž by se vám zobrazily."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"příjem textových zpráv (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Umožňuje aplikaci přijmout a zpracovat zprávy MMS. Znamená to, že aplikace může sledovat zprávy odeslané do vašeho zařízení nebo je smazat, aniž by se vám zobrazily."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Přesměrování zpráv informačních služeb"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Umožňuje aplikaci vytvořit vazbu s modulem informačních služeb za účelem přesměrovávání přijatých zpráv informačních služeb. Výstražná upozornění informačních služeb jsou v některých oblastech odesílána za účelem varování před výjimečnými událostmi. Škodlivé aplikace mohou narušit výkon či provoz vašeho zařízení během přijímání zpráv informačních služeb."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"čtení zpráv informačních služeb"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Umožňuje aplikaci číst zprávy informačních služeb přijaté ve vašem zařízení. Výstražná upozornění informačních služeb jsou v některých oblastech odesílána za účelem varování před výjimečnými událostmi. Škodlivé aplikace mohou narušit výkon či provoz vašeho zařízení během přijímání zpráv informačních služeb."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čtení zdrojů přihlášených k odběru"</string>
@@ -523,7 +521,7 @@
     <string name="permlab_useBiometric" msgid="8837753668509919318">"použití biometrického hardwaru"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Umožňuje aplikaci použít k ověření biometrický hardware"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"správa hardwaru na čtení otisků prstů"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Umožňuje aplikaci volat metody k přidání a smazání šablon otisků prstů, které budou použity."</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Umožňuje aplikaci volit metody k přidávání a mazání šablon otisků prstů, které budou použity."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"použití hardwaru na čtení otisků prstů"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Umožňuje aplikaci použít k ověření hardware na čtení otisků prstů"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"úprava hudební sbírky"</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Umožňuje aplikaci číst a zapisovat konfiguraci režimu Nerušit."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"zahájení zobrazení využití oprávnění"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Umožňuje přístup zahájit využití oprávnění jiné aplikace. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cíl zkratky přístupnosti"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Umožňuje aplikaci definovat cíl zkratky přístupnosti."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavit pravidla pro heslo"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ovládání délky a znaků povolených v heslech a kódech PIN zámku obrazovky."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Sledovat pokusy o odemknutí obrazovky"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 88900a0..0d40688 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -75,7 +75,7 @@
     <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Standarder for opkalds-id til begrænset. Næste opkald: Ikke begrænset"</string>
     <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Standarder for opkalds-id til ikke begrænset. Næste opkald: Begrænset"</string>
     <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Standarder for opkalds-id til ikke begrænset. Næste opkald: Ikke begrænset"</string>
-    <string name="serviceNotProvisioned" msgid="8614830180508686666">"Tjenesten leveres ikke!"</string>
+    <string name="serviceNotProvisioned" msgid="8614830180508686666">"Tjenesten provisioneres ikke."</string>
     <string name="CLIRPermanent" msgid="3377371145926835671">"Du kan ikke ændre indstillingen for opkalds-id\'et."</string>
     <string name="RestrictedOnDataTitle" msgid="5221736429761078014">"Ingen mobildatatjeneste"</string>
     <string name="RestrictedOnEmergencyTitle" msgid="6855466023161191166">"Det er ikke muligt at foretage nødopkald"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Tillader, at appen kan modtage og behandle sms-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"modtage tekstbeskeder (mms)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Tillader, at appen kan modtage og behandle mms-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Videresend Cell Broadcast-meddelelser"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Tillader, at appen bindes til Cell Broadcast-modulet, så Cell Broadcast-meddelelser kan videresendes, når de modtages. I nogle områder sendes der Cell Broadcast-underretninger for at advare dig om nødsituationer. Ondsindede apps kan forstyrre effektiviteten eller driften af din enhed, når den modtager en Cell Broadcast-meddelelse om en nødsituation."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"læse Cell Broadcast-meddelelser"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tillader, at appen læser Cell Broadcast-underretninger, der modtages af din enhed. I nogle områder sendes der Cell Broadcast-underretninger for at advare om nødsituationer. Ondsindede apps kan forstyrre ydelsen eller driften af ​din ​enhed, når der modtages en Cell Broadcast-meddelelse om en nødsituation."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"læse feeds, jeg abonnerer på"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Giver appen tilladelse til at kende skærmlåsens kompleksitet (høj, medium, lav eller ingen), hvilket kan afsløre oplysninger om skærmlåsens længde og type. Appen kan også foreslå brugerne at opdatere deres skærmlås til et bestemt niveau, men brugerne kan frit ignorere det og gå videre. Bemærk! Skærmlåsen gemmes ikke som almindelig tekst, så appen kender ikke den nøjagtige adgangskode."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"brug biometrisk hardware"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Tillader, at appen kan bruge biometrisk hardware til godkendelse"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"administrer fingeraftrykhardware"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"administrer hardware til fingeraftryk"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Tillader, at appen kan køre metoder til at tilføje og slette fingeraftryksskabeloner"</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"bruge fingeraftrykhardware"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Tillader, at appen kan bruge fingeraftrykhardware til godkendelse"</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"bruge hardware til fingeraftryk"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Tillader, at appen kan bruge hardware til fingeraftryk til godkendelse"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"ændre din musiksamling"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Tillader, at appen kan ændre din musiksamling."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"ændre din videosamling"</string>
@@ -536,7 +534,7 @@
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Der er ikke angivet pinkode, mønster eller adgangskode"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Der blev registreret et delvist fingeraftryk. Prøv igen."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Fingeraftrykket kunne ikke behandles. Prøv igen."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Sensoren til registrering af fingeraftryk er beskidt. Tør den af, og prøv igen."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingeraftrykslæseren er beskidt. Tør den af, og prøv igen."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Du bevægede fingeren for hurtigt. Prøv igen."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Du bevægede fingeren for langsomt. Prøv igen."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Giver appen tilladelse til at læse og redigere konfigurationen af Forstyr ikke."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"start brugen at tilladelsesvisning"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Tillader, at brugeren kan bruge en tilladelse for en app. Dette bør aldrig være nødvendigt for almindelige apps."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"mål for hjælpefunktionsgenvej"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Tillader, at en app definerer målet for en hjælpefunktionsgenvej."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Angiv regler for adgangskoder"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Tjek længden samt tilladte tegn i adgangskoder og pinkoder til skærmlåsen."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Overvåg forsøg på oplåsning af skærm"</string>
@@ -1977,7 +1973,7 @@
     <string name="notification_reply_button_accessibility" msgid="3621714652387814344">"Svar"</string>
     <string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
     <string name="mmcc_authentication_reject" msgid="5767701075994754356">"SIM-kort er ikke tilladt for tale"</string>
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"SIM-kort er ikke aktiveret for tale"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"SIM-kort er ikke provisioneret til tale"</string>
     <string name="mmcc_illegal_ms" msgid="807334478177362062">"SIM-kort er ikke tilladt for tale"</string>
     <string name="mmcc_illegal_me" msgid="1950705155760872972">"Telefon er ikke tilladt for tale"</string>
     <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"SIM-kortet <xliff:g id="SIMNUMBER">%d</xliff:g> er ikke tilladt"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 6bf5404..f051345 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Ermöglicht der App, SMS zu empfangen und zu verarbeiten. Das bedeutet, dass die App an dein Gerät gesendete Nachrichten überwachen und löschen kann, ohne sie dir anzuzeigen."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"MMS empfangen"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Ermöglicht der App, MMS zu empfangen und zu verarbeiten. Das bedeutet, dass die App an dein Gerät gesendete Nachrichten überwachen und löschen kann, ohne sie dir anzuzeigen."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Cell-Broadcast-Nachrichten weiterleiten"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Ermöglicht der App, sich mit dem Cell-Broadcast-Modul zu verbinden, um empfangene Cell-Broadcast-Nachrichten weiterzuleiten. Cell-Broadcast-Benachrichtigungen können in einigen Ländern oder Regionen gesendet werden, um dich bei Notfallsituationen zu warnen. Schädliche Apps können die Leistung oder den Betrieb deines Geräts beeinträchtigen, wenn eine Cell-Broadcast-Notfallbenachrichtigung eingeht."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"Cell Broadcast-Nachrichten lesen"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Ermöglicht der App, von deinem Gerät empfangene Cell Broadcast-Nachrichten zu lesen. Cell Broadcast-Benachrichtigungen werden an einigen Standorten gesendet, um dich über Notfallsituationen zu informieren. Schädliche Apps können die Leistung oder den Betrieb deines Geräts beeinträchtigen, wenn eine Cell Broadcast-Notfallbenachrichtigung eingeht."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"Abonnierte Feeds lesen"</string>
@@ -546,7 +544,7 @@
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Gesicht authentifiziert, bitte bestätigen"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerabdruckhardware nicht verfügbar"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerabdruck kann nicht gespeichert werden. Entferne einen vorhandenen Fingerabdruck."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Zeitüberschreitung für Fingerabdruck. Bitte versuche es noch einmal."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Zeitüberschreitung bei Fingerabdruck. Bitte versuche es noch einmal."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerabdruckvorgang abgebrochen"</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Vorgang der Fingerabdruckauthentifizierung vom Nutzer abgebrochen."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Zu viele Versuche, bitte später noch einmal versuchen"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Ermöglicht der App Lese- und Schreibzugriff auf die \"Bitte nicht stören\"-Konfiguration"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"Mit der Verwendung der Anzeigeberechtigung beginnen"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Ermöglicht dem Inhaber, die Berechtigungsnutzung für eine App zu beginnen. Sollte für normale Apps nie benötigt werden."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"Ziel der Verknüpfung für Bedienungshilfen"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Ermöglicht einer App, das Ziel der Verknüpfung für Bedienungshilfen zu definieren."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Zulässige Länge und Zeichen für Passwörter für die Displaysperre festlegen"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Versuche zum Entsperren des Displays überwachen"</string>
@@ -1596,7 +1592,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Browser starten?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Anruf annehmen?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Immer"</string>
-    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Auf \"Immer geöffnet\" festlegen"</string>
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Auf \"Immer öffnen\" festlegen"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Nur diesmal"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Einstellungen"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"Das Arbeitsprofil wird von %1$s nicht unterstützt."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 3570fc1..a360de0 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -325,7 +325,7 @@
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Εκτέλεση κινήσεων"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Επιτρέπει το πάτημα, την ολίσθηση, το πλησίασμα και άλλες κινήσεις."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Κινήσεις δακτυλικών αποτυπωμάτων"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Μπορεί να αναγνωρίσει κινήσεις που εκτελούνται στον αισθητήρα δακτυλικών αποτυπωμάτων της συσκευής."</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Μπορεί να αναγνωρίσει κινήσεις που εκτελούνται στον αισθητήρα δακτυλικού αποτυπώματος της συσκευής."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"απενεργοποιεί ή να τροποποιεί την γραμμή κατάστασης"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ορίζεται ως γραμμή κατάστασης"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων SMS. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"λαμβάνει μηνύματα κειμένου (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων MMS. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Προώθηση μηνυμάτων εκπομπής κινητής τηλεφωνίας"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Επιτρέπει στην εφαρμογή να συνδέεται στη λειτουργική μονάδα εκπομπής κινητής τηλεφωνίας, προκειμένου να προωθεί τα μηνύματα εκπομπής κινητής τηλεφωνίας κατά τη λήψη τους. Οι ειδοποιήσεις εκπομπής κινητής τηλεφωνίας προβάλλονται σε ορισμένες τοποθεσίες, για να σας προειδοποιήσουν σχετικά με καταστάσεις έκτακτης ανάγκης. Οι κακόβουλες εφαρμογές μπορεί να επηρεάσουν την απόδοση ή τη λειτουργία της συσκευής σας κατά τη λήψη μιας εκπομπής κινητής τηλεφωνίας έκτακτης ανάγκης."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"διαβάζει μηνύματα που έχουν μεταδοθεί μέσω κινητού τηλεφώνου"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Επιτρέπει στην εφαρμογή την ανάγνωση μηνυμάτων που έχουν μεταδοθεί μέσω κινητού τηλεφώνου και έχουν ληφθεί από τη συσκευή σας. Ειδοποιήσεις που μεταδίδονται μέσω κινητού παραδίδονται σε ορισμένες τοποθεσίες για να σας προειδοποιήσουν για καταστάσεις έκτακτης ανάγκης. Κακόβουλες εφαρμογές ενδέχεται να παρεμποδίσουν την απόδοση ή τη λειτουργία της συσκευής σας κατά τη λήψη μετάδοσης μέσω κινητού σχετικά με μια επείγουσα κατάσταση."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"διαβάζει ροές δεδομένων στις οποίες έχετε εγγραφεί"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Επιτρέπει στην εφαρμογή να μάθει το επίπεδο πολυπλοκότητας του κλειδώματος οθόνης (υψηλό, μέσο, χαμηλό ή κανένα), το οποίο υποδεικνύει το πιθανό εύρος του μήκους και του τύπου κλειδώματος οθόνης. Η εφαρμογή μπορεί επίσης να προτείνει στους χρήστες να ενημερώσουν το κλείδωμα οθόνης σε ένα συγκεκριμένο επίπεδο, όμως οι χρήστες μπορούν να την αγνοήσουν και να συνεχίσουν. Λάβετε υπόψη ότι το κλείδωμα οθόνης δεν αποθηκεύεται σε απλό κείμενο. Συνεπώς, η εφαρμογή δεν γνωρίζει τον κωδικό."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"χρήση βιομετρικού εξοπλισμού"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί βιομετρικό εξοπλισμό για έλεγχο ταυτότητας"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"διαχειρίζεται τον εξοπλισμό δακτυλικού αποτυπώματος"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Επιτρέπει στην εφαρμογή να επικαλείται μεθόδους για την προσθήκη και τη διαγραφή προτύπων μοναδικού χαρακτηριστικού για χρήση."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"χρησιμοποιεί τον εξοπλισμό δακτυλικού αποτυπώματος"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί εξοπλισμό μοναδικού χαρακτηριστικού για έλεγχο ταυτότητας"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"διαχείριση εξοπλισμού δακτυλικού αποτυπώματος"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Επιτρέπει στην εφαρμογή να επικαλείται μεθόδους για την προσθήκη και τη διαγραφή προτύπων δακτυλικών αποτυπωμάτων για χρήση."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"χρήση εξοπλισμού δακτυλικού αποτυπώματος"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί εξοπλισμό δακτυλικού αποτυπώματος για έλεγχο ταυτότητας"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"τροποποίηση της μουσικής συλλογής σας"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Επιτρέπει στην εφαρμογή να τροποποιήσει τη μουσική συλλογή σας."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"τροποποίηση της συλλογής βίντεό σας"</string>
@@ -534,9 +532,9 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Δεν αναγνωρίστηκε"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Ο έλεγχος ταυτότητας ακυρώθηκε"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Δεν έχει οριστεί PIN, μοτίβο ή κωδικός πρόσβασης"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Εντοπίστηκε μερικό μοναδικό χαρακτηριστικό. Δοκιμάστε ξανά."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Δεν ήταν δυνατή η επεξεργασία του μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Ο αισθητήρας μοναδικού χαρακτηριστικού δεν είναι καθαρός. Καθαρίστε τον και δοκιμάστε ξανά."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Εντοπίστηκε μόνο μέρος του δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Δεν ήταν δυνατή η επεξεργασία του δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Ο αισθητήρας δακτυλικού αποτυπώματος δεν είναι καθαρός. Καθαρίστε τον και δοκιμάστε ξανά."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Πολύ γρήγορη κίνηση δαχτύλου. Δοκιμάστε ξανά."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Πολύ αργή κίνηση δαχτύλου. Δοκιμάστε ξανά."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -544,16 +542,16 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Η ταυτότητα του δακτυλικού αποτυπώματος ελέγχθηκε"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Έγινε έλεγχος ταυτότητας προσώπου"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Έγινε έλεγχος ταυτότητας προσώπου, πατήστε \"Επιβεβαίωση\""</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Ο εξοπλισμός μοναδικού χαρακτηριστικού δεν είναι διαθέσιμος."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Δεν είναι δυνατή η αποθήκευση μοναδικού χαρακτηριστικού. Καταργήστε το υπάρχον μοναδικό χαρακτηριστικό."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Λήξη χρονικού ορίου μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Η λειτουργία μοναδικού χαρακτηριστικού ακυρώθηκε."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Ο εξοπλισμός δακτυλικού αποτυπώματος δεν είναι διαθέσιμος."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Δεν είναι δυνατή η αποθήκευση του δακτυλικού αποτυπώματος. Καταργήστε το υπάρχον δακτυλικό αποτύπωμα."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Λήξη χρονικού ορίου δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Η λειτουργία δακτυλικού αποτυπώματος ακυρώθηκε."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Η λειτουργία δακτυλικού αποτυπώματος ακυρώθηκε από τον χρήστη."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Πάρα πολλές προσπάθειες. Δοκιμάστε ξανά αργότερα."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Πάρα πολλές προσπάθειες. Ο αισθητήρας δακτυλικών αποτυπωμάτων απενεργοποιήθηκε."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Δοκιμάστε ξανά."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Δεν έχουν καταχωριστεί δακτυλικά αποτυπώματα."</string>
-    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Αυτή η συσκευή δεν διαθέτει αισθητήρα δακτυλικών αποτυπωμάτων."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Αυτή η συσκευή δεν διαθέτει αισθητήρα δακτυλικού αποτυπώματος."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Δάχτυλο <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Επιτρέπει στην εφαρμογή την εγγραφή και τη σύνταξη διαμόρφωσης για τη λειτουργία \"Μην ενοχλείτε\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"έναρξη χρήσης άδειας προβολής"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Επιτρέπει στον κάτοχο να ξεκινήσει τη χρήση της άδειας για μια εφαρμογή. Δεν απαιτείται ποτέ για κανονικές εφαρμογές."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"στόχος συντόμευσης προσβασιμότητας"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Επιτρέπει σε μια εφαρμογή να καθορίσει τον στόχο της συντόμευσης προσβασιμότητας."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ελέγξτε την έκταση και τους επιτρεπόμενους χαρακτήρες σε κωδικούς πρόσβασης κλειδώματος οθόνης και PIN."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index e1d9875..1e0e93a 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Allows the app to receive and process SMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receive text messages (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Forward cell broadcast messages"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"read mobile broadcast messages"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"read subscribed feeds"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Allows the app to read and write Do Not Disturb configuration."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"start view permission usage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Allows the holder to start the permission usage for an app. Should never be needed for normal apps."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"accessibility shortcut target"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Allows an app to define the accessibility shortcut target."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitor screen unlock attempts"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 56b54d9..4deaf2e 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Allows the app to receive and process SMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receive text messages (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Forward cell broadcast messages"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"read mobile broadcast messages"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"read subscribed feeds"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Allows the app to read and write Do Not Disturb configuration."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"start view permission usage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Allows the holder to start the permission usage for an app. Should never be needed for normal apps."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"accessibility shortcut target"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Allows an app to define the accessibility shortcut target."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitor screen unlock attempts"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index e1d9875..1e0e93a 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Allows the app to receive and process SMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receive text messages (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Forward cell broadcast messages"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"read mobile broadcast messages"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"read subscribed feeds"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Allows the app to read and write Do Not Disturb configuration."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"start view permission usage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Allows the holder to start the permission usage for an app. Should never be needed for normal apps."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"accessibility shortcut target"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Allows an app to define the accessibility shortcut target."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitor screen unlock attempts"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index e1d9875..1e0e93a 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Allows the app to receive and process SMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receive text messages (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Forward cell broadcast messages"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"read mobile broadcast messages"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"read subscribed feeds"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Allows the app to read and write Do Not Disturb configuration."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"start view permission usage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Allows the holder to start the permission usage for an app. Should never be needed for normal apps."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"accessibility shortcut target"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Allows an app to define the accessibility shortcut target."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitor screen unlock attempts"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index c4d3157..5fe1bb1 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‏‏‎‏‏‎Allows the app to receive and process SMS messages. This means the app could monitor or delete messages sent to your device without showing them to you.‎‏‎‎‏‎"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‎‎receive text messages (MMS)‎‏‎‎‏‎"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎Allows the app to receive and process MMS messages. This means the app could monitor or delete messages sent to your device without showing them to you.‎‏‎‎‏‎"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‏‎‎‎Forward cell broadcast messages‎‏‎‎‏‎"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎‏‏‏‎‎‏‎Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received.‎‏‎‎‏‎"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‏‏‎‎‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‎‏‏‎‏‎‏‏‎‏‏‏‎‏‎‏‏‎‏‎‏‏‎‎read cell broadcast messages‎‏‎‎‏‎"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‎‏‏‏‎‎‎‏‏‎Allows the app to read cell broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received.‎‏‎‎‏‎"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‏‏‎‎read subscribed feeds‎‏‎‎‏‎"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‎‎‎‎‎‏‎‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‎Allows the app to read and write Do Not Disturb configuration.‎‏‎‎‏‎"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‎‏‏‏‏‎‎‎‎start view permission usage‎‏‎‎‏‎"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎‎‎Allows the holder to start the permission usage for an app. Should never be needed for normal apps.‎‏‎‎‏‎"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‎‏‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‏‎‎‏‏‎‎‏‎accessibility shortcut target‎‏‎‎‏‎"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎Allows an app to define the accessibility shortcut target.‎‏‎‎‏‎"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‏‎‏‎‎‏‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‏‎Set password rules‎‏‎‎‏‎"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎Control the length and the characters allowed in screen lock passwords and PINs.‎‏‎‎‏‎"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‎‏‎‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎Monitor screen unlock attempts‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 30f8ba7..feb4aee 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que la aplicación reciba y procese mensajes SMS, lo que significa que podría controlar o eliminar mensajes enviados al dispositivo sin mostrártelos."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recibir mensajes de texto (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite que la aplicación reciba y procese mensajes MMS, lo que significa que podría controlar o eliminar mensajes enviados al dispositivo sin mostrártelos."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Reenviar mensajes de emisión móvil"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite que la app se vincule al módulo de emisión móvil para reenviar los mensajes de este tipo a medida que se reciben. En algunas ubicaciones, se envían alertas de emisión móvil para advertirte en situaciones de emergencia. Es posible que las apps maliciosas interfieran con el rendimiento o el funcionamiento de tu dispositivo cuando recibes una emisión móvil de emergencia."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"Leer mensajes de difusión móvil"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite a la aplicación leer los mensajes de difusión móvil que recibe tu dispositivo. En algunas ubicaciones, las alertas de difusión móvil se envían para informar situaciones de emergencia. Las aplicaciones maliciosas pueden afectar el rendimiento o funcionamiento de tu dispositivo cuando se recibe un un mensaje de difusión móvil de emergencia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"leer canales suscritos"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permite que la aplicación lea y modifique la configuración de la función No interrumpir."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"iniciar uso de permiso de vista"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite que el propietario inicie el uso de permisos para una app. No debería requerirse para apps normales."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"orientación del acceso directo de accesibilidad"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite que una app defina la orientación del acceso directo de accesibilidad."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controlar la longitud y los caracteres permitidos en las contraseñas y los PIN para el bloqueo de pantalla."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Supervisa los intentos para desbloquear la pantalla"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 15e662c..75510b3 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -230,7 +230,7 @@
     <string name="global_action_bug_report" msgid="7934010578922304799">"Informe de error"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Finalizar sesión"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de pantalla"</string>
-    <string name="bugreport_title" msgid="5981047024855257269">"Informe de errores"</string>
+    <string name="bugreport_title" msgid="5981047024855257269">"Informar de un error"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Se recopilará información sobre el estado actual de tu dispositivo y se enviará por correo electrónico. Pasarán unos minutos desde que empiece a generarse el informe de errores hasta que se envíe."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Informe interactivo"</string>
     <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"Usa esta opción en la mayoría de los casos. Te permite realizar un seguimiento del progreso del informe, introducir más información sobre el problema y hacer capturas de pantalla. Es posible que se omitan algunas secciones menos utilizadas y que requieran más tiempo."</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que la aplicación reciba y procese mensajes MMS, lo que significa que podría utilizar este permiso para controlar o eliminar mensajes enviados al dispositivo sin mostrárselos al usuario."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recibir mensajes de texto (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite que la aplicación reciba y procese mensajes MMS, lo que significa que podría utilizar este permiso para controlar o eliminar mensajes enviados al dispositivo sin mostrárselos al usuario."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Reenviar mensajes de difusión móvil"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite que la aplicación se vincule con el módulo de difusión móvil para reenviar los mensajes de ese tipo en cuanto se reciben. En ciertas ubicaciones se envían alertas de difusión móvil para avisar de situaciones de emergencia. Cuando se recibe una alerta de difusión móvil de emergencia, ciertas aplicaciones malintencionadas podrían interferir en el rendimiento o en el funcionamiento del dispositivo."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"leer mensajes de difusión móvil"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite que la aplicación lea mensajes de difusión móvil que haya recibido el dispositivo. Las alertas de difusión móvil se envían en algunas ubicaciones para avisar de situaciones de emergencia. Es posible que las aplicaciones malintencionadas interfieran en el rendimiento o en el funcionamiento del dispositivo si se recibe una alerta de difusión móvil de emergencia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"leer feeds a los que está suscrito el usuario"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permite que la aplicación lea y modifique la configuración de No molestar."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"iniciar uso de permiso de visualización"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite que el titular inicie el uso de permisos de una aplicación. Las aplicaciones normales no deberían necesitar nunca este permiso."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"objetivo de atajo de accesibilidad"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite que una aplicación defina el objetivo de un atajo de accesibilidad."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controla la longitud y los caracteres permitidos en los PIN y en las contraseñas de bloqueo de pantalla."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Supervisar los intentos de desbloqueo de pantalla"</string>
@@ -1195,7 +1191,7 @@
     <string name="unsupported_display_size_show" msgid="7969129195360353041">"Mostrar siempre"</string>
     <string name="unsupported_compile_sdk_message" msgid="4253168368781441759">"<xliff:g id="APP_NAME">%1$s</xliff:g> se diseñó para una versión incompatible de Android OS y puede que funcione de forma inesperada. Es posible que haya una versión actualizada de la aplicación."</string>
     <string name="unsupported_compile_sdk_show" msgid="2681877855260970231">"Mostrar siempre"</string>
-    <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"Comprobar actualizaciones"</string>
+    <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"Buscar actualizaciones"</string>
     <string name="smv_application" msgid="3307209192155442829">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) ha infringido su política StrictMode autoaplicable."</string>
     <string name="smv_process" msgid="5120397012047462446">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> ha infringido su política StrictMode autoaplicable."</string>
     <string name="android_upgrading_title" product="default" msgid="7513829952443484438">"El teléfono se está actualizando…"</string>
@@ -1914,7 +1910,7 @@
     <string name="work_mode_off_message" msgid="5130856710614337649">"Tus aplicaciones, notificaciones, datos y otras funciones del perfil de trabajo se activarán"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Activar"</string>
     <string name="deprecated_target_sdk_message" msgid="1449696506742572767">"Esta aplicación se ha diseñado para una versión anterior de Android y es posible que no funcione correctamente. Busca actualizaciones o ponte en contacto con el desarrollador."</string>
-    <string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Comprobar actualizaciones"</string>
+    <string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Buscar actualizaciones"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Tienes mensajes nuevos"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Abre la aplicación de SMS para ver el mensaje"</string>
     <string name="profile_encrypted_title" msgid="4260432497586829134">"Algunas funciones limitadas"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 093f7d7..0e7befd 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Võimaldab rakendusel vastu võtta ja töödelda SMS-sõnumeid. See tähendab, et rakendus võib jälgida või kustutada teie seadmele saadetud sõnumeid neid teile näitamata."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"võtke vastu tekstisõnumeid (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Võimaldab rakendusel vastu võtta ja töödelda multimeediumsõnumeid. See tähendab, et rakendus võib jälgida või kustutada teie seadmele saadetud sõnumeid neid teile näitamata."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Kärjeteadete edasisaatmine"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Võimaldab rakendusel luua ühenduse kärjeteadete mooduliga, et saabunud kärjeteateid edasi saata. Kärjeteateid edastatakse mõnes asukohas eriolukorrast teavitamiseks. Pahatahtlikud rakendused võivad seadme toimivust või tööd eriolukorra kärjeteate vastuvõtmisel segada."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"mobiilsidesõnumite lugemine"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Võimaldab rakendusel lugeda seadme vastu võetud mobiilsidesõnumeid. Mobiilsidemärguandeid edastatakse mõnes asukohas eriolukorrast teavitamiseks. Pahatahtlikud rakendused võivad segada seadme toimivust või tööd eriolukorra sõnumi vastuvõtmisel."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"loe tellitud kanaleid"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Võimaldab rakendusel lugeda ja kirjutada funktsiooni Mitte segada seadistusi."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"vaatamisloa kasutamise alustamine"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Võimaldab omanikul rakenduse puhul alustada loa kasutamist. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"juurdepääsetavuse otsetee sihtmärk"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Lubab rakendusel määrata juurdepääsetavuse otsetee sihtmärgi."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Parooli reeglite määramine"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Juhitakse ekraaniluku paroolide ja PIN-koodide pikkusi ning lubatud tähemärkide seadeid."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Ekraani avamiskatsete jälgimine"</string>
@@ -1145,7 +1141,7 @@
     <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Linkide avamine rakendusega <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
     <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Ava teenuse <xliff:g id="HOST">%1$s</xliff:g> lingid rakendusega <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Juudep. andmine"</string>
-    <string name="whichEditApplication" msgid="144727838241402655">"Muutmine:"</string>
+    <string name="whichEditApplication" msgid="144727838241402655">"Redigeeri rakendusega:"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Muutmine rakendusega %1$s"</string>
     <string name="whichEditApplicationLabel" msgid="7183524181625290300">"Muuda"</string>
     <string name="whichSendApplication" msgid="5803792421724377602">"Jagamine"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 53b1a38..22391dc 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"jaso testu-mezuak (MMSak)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Desbideratu sare mugikor bidezko igorpen-mezuak"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Sare mugikor bidezko igorpen-modulura lotzeko baimena ematen dio aplikazioari, sare mugikor bidezko igorpen-mezuak jaso ahala desbideratu ahal izateko. Sare mugikor bidezko igorpen-alertak kokapen batzuetan entregatzen dira larrialdi-egoeren berri emateko. Sare mugikor bidezko larrialdi-igorpenak jasotzean, aplikazio maltzurrek gailuaren errendimenduari edota funtzionamenduari eragin diezaiokete."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"irakurri sare mugikor bidezko igorpen-mezuak"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Gailuak jasotako sare mugikor bidezko igorpenen mezuak irakurtzeko baimena ematen die aplikazioei. Sare mugikor bidezko igorpen-alertak kokapen batzuetan ematen dira larrialdi-egoeren berri emateko. Aplikazio gaiztoek gailuaren errendimendua edo funtzionamendua oztopa dezakete larrialdi-igorpen horietako bat jasotzen denean."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"irakurri harpidetutako jarioak"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Pantailaren blokeoaren konplexutasun-maila (handia, ertaina, txikia edo bat ere ez) jakiteko aukera ematen dio aplikazioari. Informazio horrekin, pantailaren blokeoaren luzera-barruti edo mota posiblea ondoriozta liteke. Halaber, pantailaren blokeoa maila jakin batera igotzeko iradoki diezaieke aplikazioak erabiltzaileei, baina horri ez ikusi egin eta aplikazioa erabiltzen jarraitzeko aukera dute erabiltzaileek. Kontuan izan pantailaren blokeoa ez dela gordetzen testu arrunt gisa; beraz, aplikazioak ez du jakingo pasahitz zehatza zein den."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"Erabili hardware biometrikoa"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Autentifikatzeko hardware biometrikoa erabiltzeko baimena ematen die aplikazioei."</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"kudeatu erreferentzia-gako digitalen hardwarea"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"kudeatu hatz-marken hardwarea"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Erreferentzia-gako digitalen txantiloiak gehitzeko eta ezabatzeko metodoei dei egitea baimentzen die aplikazioei."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"erabili erreferentzia-gako digitalen hardwarea"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Autentifikatzeko erreferentzia-gako digitalen hardwarea erabiltzeko baimena ematen die aplikazioei."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"erabili hatz-marken hardwarea"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Autentifikatzeko hatz-marken hardwarea erabiltzeko baimena ematen die aplikazioei."</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"musika-bilduma aldatu"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Musika-bilduma aldatzeko baimena ematen die aplikazioei."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"bideo-bilduma aldatu"</string>
@@ -544,7 +542,7 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Autentifikatu da hatz-marka"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Autentifikatu da aurpegia"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Autentifikatu da aurpegia; sakatu Berretsi"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hatz-markaren hardwarea ez dago erabilgarri."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hatz-marken hardwarea ez dago erabilgarri."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Ezin da gorde hatz-marka digitala. Kendu lehendik gordeta duzunetako bat."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Hatz-markak prozesatzeko denbora-muga gainditu da. Saiatu berriro."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Hatz-markaren eragiketa bertan behera utzi da."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"\"Ez molestatu\" konfigurazioa irakurtzeko eta bertan idazteko baimena ematen die aplikazioei."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"hasi ikusteko baimena erabiltzen"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Aplikazioaren baimena erabiltzen hasteko baimena ematen die titularrei. Aplikazio normalek ez lukete beharko."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"erabilerraztasun-lasterbidearen helburua"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Erabilerraztasun-lasterbidearen helburua zehazteko baimena ematen dio aplikazioari."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ezarri pasahitzen arauak"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolatu pantaila blokeoaren pasahitzen eta PINen luzera eta onartutako karaktereak."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Gainbegiratu pantaila desblokeatzeko saiakerak"</string>
@@ -1556,7 +1552,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Aukera gehiago"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Barneko biltegiratze partekatua"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Barneko memoria partekatua"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD txartela"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD txartela"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"USB bidezko unitatea"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 2b849d5..33421c0 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"به برنامه اجازه می‌دهد پیامک‌ها را دریافت و پردازش کند. این یعنی برنامه می‌تواند پیام‌های ارسالی به دستگاه شما را بدون نمایش آن‌ها به شما حذف یا کنترل کند."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"دریافت پیام‌های نوشتاری (فراپیام)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"به برنامه اجازه می‌دهد پیام‌های فراپیام را دریافت و پردازش کند. این یعنی برنامه می‌تواند پیام‌های ارسالی به دستگاه شما را بدون نمایش آن‌ها به شما حذف یا کنترل کند."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"بازارسال پیام‌های پخش سلولی"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"به برنامه امکان می‌دهد به مدول پخش سلولی متصل شود تا پیام‌های پخش سلولی را به محض دریافت بازارسال کند. هشدارهای پخش سلولی در برخی از موقعیت‌های مکانی ارسال می‌شوند تا موقعیت‌های اضطراری را به شما اعلام کنند. وقتی پخش سلولی دریافت می‌شود، ممکن است برنامه‌های مخرب در عملکرد یا کارکرد دستگاه شما اختلال ایجاد کنند."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"خواندن پیام‌های پخش سلولی"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"‏به برنامه اجازه می‎دهد پیام‌های پخش سلولی دستگاه شما را بخواند. هشدارهای پخش سلولی در برخی از موقعیت‌های مکانی تحویل داده می‎شوند تا موقعیت‌های اضطراری را به شما اعلام کنند. وقتی پخش سلولی دریافت می‎شود، ممکن است برنامه‎های مخرب در عملکرد یا کارکرد دستگاه شما اختلال ایجاد کنند."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"خواندن فیدهای مشترک"</string>
@@ -553,7 +551,7 @@
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"تلاش‌های بسیاری زیادی انجام شده است. حسگر اثر انگشت غیرفعال شد."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"دوباره امتحان کنید."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"اثر انگشتی ثبت نشده است."</string>
-    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"این دستگاه حسگر اثرانگشت ندارد."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"این دستگاه حسگر اثر انگشت ندارد."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"انگشت <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"به برنامه امکان می‌دهد پیکربندی «مزاحم نشوید» را بخواند و بنویسد."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"شروع مشاهده استفاده از مجوز"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"به دارنده اجازه شروع استفاده از مجوز را برای برنامه می‌دهد. هرگز برای برنامه‌های معمول نیاز نیست."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"مقصد میان‌بر دسترس‌پذیری"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"به برنامه اجازه می‌دهد مقصد میانبر دسترس‌پذیری را تعریف کند."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین گذرواژه"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"کنترل طول و نوع نویسه‌هایی که در گذرواژه و پین قفل صفحه مجاز است."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"پایش تلاش‌های باز کردن قفل صفحه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index c18e5bf..124a160 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -332,7 +332,7 @@
     <string name="permdesc_statusBarService" msgid="716113660795976060">"Antaa sovelluksen sijaita tilapalkissa."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"laajentaa/tiivistää tilarivin"</string>
     <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"Antaa sovelluksen laajentaa tai tiivistää tilarivin."</string>
-    <string name="permlab_install_shortcut" msgid="4279070216371564234">"asenna pikakuvakkeita"</string>
+    <string name="permlab_install_shortcut" msgid="4279070216371564234">"asentaa pikakuvakkeita"</string>
     <string name="permdesc_install_shortcut" msgid="8341295916286736996">"Antaa sovelluksen lisätä aloitusruudun pikakuvakkeita ilman käyttäjän toimia."</string>
     <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"poista pikakuvakkeita"</string>
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Antaa sovelluksen poistaa aloitusruudun pikakuvakkeita ilman käyttäjän toimia."</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Antaa sovelluksen vastaanottaa ja käsitellä tekstiviestejä. Sovellus voi valvoa tai poistaa laitteeseesi lähetettyjä viestejä näyttämättä niitä sinulle."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"vastaanota tekstiviestejä (multimedia)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Antaa sovelluksen vastaanottaa ja käsitellä multimediaviestejä. Sovellus voi valvoa tai poistaa laitteeseesi lähetettyjä viestejä näyttämättä niitä sinulle."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Lähetä solulähetysviestit edelleen"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Sallii sovelluksen sitoutua solulähetysmoduuliin lähettääkseen solulähetysviestejä edelleen sitä mukaa kun ne saapuvat. Solulähetysilmoitusten avulla ilmoitetaan hätätilanteista joissakin paikoissa. Haitalliset sovellukset voivat häiritä laitteen toimintaa laitteen vastaanottaessa hätätilanteeseen liittyvän solulähetysviestin."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lue tiedotteita"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Antaa sovelluksen lukea laitteesi vastaanottamia tiedotteita. Tiedotteiden avulla ilmoitetaan hätätilanteista joissakin paikoissa. Haitalliset sovellukset voivat häiritä laitteen toimintaa laitteen vastaanottaessa hätätiedotteen."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lukea tilattuja syötteitä"</string>
@@ -386,7 +384,7 @@
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Antaa sovelluksen noutaa sen koodin, tietojen ja välimuistin koot."</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"muokkaa järjestelmän asetuksia"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"Antaa sovelluksen muokata järjestelmän asetustietoja. Haitalliset sovellukset voivat vahingoittaa järjestelmän määritystä."</string>
-    <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"suorita laitteen käynnistyessä"</string>
+    <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"suorittaa laitteen käynnistyessä"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Antaa sovelluksen käynnistyä heti, kun laite on käynnistynyt. Tämä voi pidentää tablet-laitteen käynnistysaikaa ja hidastaa sen yleistä käyttöä sovelluksen ollessa aina käynnissä."</string>
     <string name="permdesc_receiveBootCompleted" product="tv" msgid="6725487837446317527">"Antaa sovelluksen käynnistyä heti, kun laite on käynnistynyt. Tämä voi pidentää Android TV ‑laitteen käynnistysaikaa ja hidastaa sen yleistä käyttöä sovelluksen ollessa aina käynnissä."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Antaa sovelluksen käynnistyä heti, kun laite on käynnistynyt. Tämä voi pidentää puhelimen käynnistysaikaa ja hidastaa puhelimen yleistä käyttöä sovelluksen ollessa aina käynnissä."</string>
@@ -440,7 +438,7 @@
     <string name="permdesc_camera" msgid="5392231870049240670">"Tämä sovellus voi ottaa kameralla kuvia ja videoita koska tahansa."</string>
     <string name="permlab_systemCamera" msgid="4074081285026193898">"Salli sovellukselle tai palvelulle pääsy järjestelmän kameroihin, jotta se voi ottaa kuvia ja nauhoittaa videoita"</string>
     <string name="permdesc_systemCamera" msgid="6488131672529669229">"Tämä käyttöoikeuden saanut | järjestelmäsovellus voi ottaa järjestelmän kameralla kuvia ja videoita koska tahansa. Sovelluksella on oltava myös android.permission.CAMERA-käyttöoikeus"</string>
-    <string name="permlab_vibrate" msgid="7696427026057705834">"hallitse värinää"</string>
+    <string name="permlab_vibrate" msgid="7696427026057705834">"hallita värinää"</string>
     <string name="permdesc_vibrate" msgid="6284989245902300945">"Antaa sovelluksen hallita värinää."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"soittaa puhelinnumeroihin suoraan"</string>
     <string name="permdesc_callPhone" msgid="3740797576113760827">"Antaa sovelluksen soittaa puhelinnumeroihin kysymättä sinulta. Tämä voi aiheuttaa odottamattomia kuluja tai puheluita. Huomaa, että tämä ei anna sovellukselle lupaa soittaa hätänumeroihin. Haitalliset sovellukset voivat aiheuttaa sinulle kuluja soittamalla puheluita ilman lupaa."</string>
@@ -478,7 +476,7 @@
     <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Antaa sovelluksen tarkastella tablet-laitteeseen tallennettuja tilejä. Näihin voivat kuulua myös asentamiesi sovelluksien luomat tilit."</string>
     <string name="permdesc_getAccounts" product="tv" msgid="1394648459318596337">"Antaa sovelluksen noutaa Android TV ‑laitteen tuntemien tilien listan. Tileihin voi kuulua myös asennettujen sovellusten luomia tilejä."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Antaa sovelluksen tarkastella puhelimeen tallennettuja tilejä. Näihin voivat kuulua myös asentamiesi sovelluksien luomat tilit."</string>
-    <string name="permlab_accessNetworkState" msgid="4951027964348974773">"tarkastele verkkoyhteyksiä"</string>
+    <string name="permlab_accessNetworkState" msgid="4951027964348974773">"tarkastella verkkoyhteyksiä"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Antaa sovelluksen tarkastella verkkoyhteyksiä koskevia tietoja, kuten mitä verkkoja on olemassa ja mihin on muodostettu yhteys."</string>
     <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"saada täydet verkon käyttöoikeudet"</string>
     <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Antaa sovelluksen luoda verkkovastakkeita ja käyttää muokattuja verkkoprotokollia. Tietoja voidaan lähettää verkkoon selaimen ja muiden sovellusten avulla, joten tätä lupaa ei tarvita tietojen lähettämiseksi."</string>
@@ -486,7 +484,7 @@
     <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Antaa sovelluksen muuttaa verkkoyhteyden tilaa."</string>
     <string name="permlab_changeTetherState" msgid="5952584964373017960">"internetyhteyden jakamisen muuttaminen"</string>
     <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Antaa sovelluksen muuttaa internetyhteyden jakamisen tilaa."</string>
-    <string name="permlab_accessWifiState" msgid="5202012949247040011">"näytä Wi-Fi-yhteydet"</string>
+    <string name="permlab_accessWifiState" msgid="5202012949247040011">"nähdä Wi-Fi-yhteydet"</string>
     <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Antaa sovelluksen tarkastella Wi-Fi-verkkoja koskevia tietoja, kuten onko Wi-Fi käytössä ja mihin Wi-Fi-laitteisiin on muodostettu yhteys."</string>
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"muodosta ja katkaise Wi-Fi-yhteys"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Antaa sovelluksen yhdistää Wi-Fi-tukiasemiin tai katkaista yhteyden sekä tehdä muutoksia määritettyihin Wi-Fi-verkkoihin."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Sallii sovelluksen lukea ja muokata Älä häiritse -tilan asetuksia."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"aloita katseluoikeuksien käyttö"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Antaa luvanhaltijan käynnistää sovelluksen käyttöoikeuksien käytön. Ei tavallisten sovelluksien käyttöön."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"esteettömyystilan pikakuvakkeen kohde"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Sallii sovelluksen määrittää kohteen esteettömystilan pikakuvakkeelle."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Asentaa salasanasäännöt"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Hallinnoida ruudun lukituksen salasanoissa ja PIN-koodeissa sallittuja merkkejä ja niiden pituutta."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Tarkkailla näytön avaamisyrityksiä"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 3bd5c23..ecfdcd2 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permet à l\'application de recevoir et de traiter les messages texte. Cette autorisation lui donne la possibilité de surveiller ou de supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recevoir des messages multimédias"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permet à l\'application de recevoir et de traiter les messages multimédias. Cette autorisation lui donne la possibilité de surveiller ou de supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Transférer les messages de diffusion cellulaire"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permet à l\'application d\'établir un lien avec le module de diffusion cellulaire afin de transférer les messages de diffusion cellulaire à mesure de leur réception. Dans certaines régions, des alertes de diffusion cellulaire sont envoyées afin de vous avertir de situations d\'urgence. Des applications malveillantes peuvent interférer avec les performances ou le fonctionnement de votre appareil lors de la réception d\'une alerte d\'urgence par diffusion cellulaire."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lire les messages de diffusion cellulaire"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permet à l\'application de lire les messages de diffusion cellulaire que votre appareil reçoit. Dans certaines zones géographiques, des alertes vous sont envoyées afin de vous prévenir en cas de situation d\'urgence. Des applications malveillantes peuvent venir perturber les performances ou le fonctionnement de votre appareil lors de la réception d\'un message de diffusion cellulaire."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lire les flux auxquels vous êtes abonné"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permet à l\'application de consulter et de modifier la configuration du mode Ne pas déranger."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"démarrer l\'affichage de l\'usage des autorisations"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permet au détenteur de démarrer l\'usage des autorisations pour une application. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cible du raccourci d\'accessibilité"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permet à une application de définir la cible du raccourci d\'accessibilité."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Gérer le nombre et le type de caractères autorisés dans les mots de passe et les NIP de verrouillage de l\'écran."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1588,7 +1584,7 @@
     <string name="serial_number" msgid="758814067660862493">"Numéro de série :"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Empreintes :"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"Empreinte digitale SHA-256 :"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"Empreinte digitale SHA-1 :"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Empreinte SHA-1 :"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Tout afficher"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Sélectionnez une activité"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Partagez avec"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 8520c13..1a44b79 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permet à l\'application de recevoir et de traiter les SMS. Cette autorisation lui donne la possibilité de surveiller ou supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recevoir des messages texte (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permet à l\'application de recevoir et de traiter les MMS. Cette autorisation lui donne la possibilité de surveiller ou supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Transférer les messages reçus via un canal de diffusion cellulaire"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Autorise l\'application à établir une connexion avec le module de diffusion cellulaire afin de transférer les messages reçus via un canal de diffusion cellulaire. Des alertes de diffusion cellulaire sont générées dans certaines régions afin de vous avertir de situations d\'urgence. Des applications malveillantes peuvent interférer avec les performances ou le fonctionnement de votre appareil lors de la réception d\'une alerte d\'urgence par diffusion cellulaire."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lire les messages reçus via un canal de diffusion cellulaire"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permet à l\'application de lire les messages que votre appareil reçoit via un canal de diffusion cellulaire. Dans certaines zones géographiques, des alertes vous sont envoyées afin de vous prévenir en cas de situation d\'urgence. Les applications malveillantes peuvent venir perturber les performances ou le fonctionnement de votre appareil lorsqu\'un message est reçu via un canal de diffusion cellulaire."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lire les flux auxquels vous êtes abonné"</string>
@@ -534,7 +532,7 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Non reconnu"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Authentification annulée"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Aucun code, schéma ni mot de passe n\'est défini"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Empreinte numérique partiellement détectée. Veuillez réessayer."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Empreinte digitale partiellement détectée. Veuillez réessayer."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossible de reconnaître l\'empreinte digitale. Veuillez réessayer."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Le lecteur d\'empreinte digitale est sale. Veuillez le nettoyer, puis réessayer."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Vous avez déplacé votre doigt trop rapidement. Veuillez réessayer."</string>
@@ -544,10 +542,10 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Empreinte digitale authentifiée"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Visage authentifié"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Visage authentifié, veuillez appuyer sur \"Confirmer\""</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Matériel d\'empreinte numérique indisponible."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Impossible d\'enregistrer l\'empreinte numérique. Veuillez supprimer une empreinte."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Délai de détection de l\'empreinte numérique expiré. Veuillez réessayer."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Opération d\'empreinte numérique annulée."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Matériel d\'empreinte digitale indisponible."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Impossible d\'enregistrer l\'empreinte digitale. Veuillez en supprimer une autre."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Délai de détection de l\'empreinte digitale expiré. Veuillez réessayer."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Opération d\'empreinte digitale annulée."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Opération d\'authentification par empreinte digitale annulée par l\'utilisateur."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Trop de tentatives. Veuillez réessayer plus tard."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Trop de tentatives. Lecteur d\'empreinte digitale désactivé."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permet à l\'application de consulter et de modifier la configuration du mode Ne pas déranger."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"activer l\'utilisation de l\'autorisation d\'affichage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permet à l\'application autorisée d\'activer l\'utilisation de l\'autorisation pour une application. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cible du raccourci d\'accessibilité"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Autorise une application à définir la cible du raccourci d\'accessibilité."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Gérer le nombre et le type de caractères autorisés dans les mots de passe et les codes d\'accès de verrouillage de l\'écran"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Gérer les tentatives de déverrouillage de l\'écran"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 78c7d03..933fbab 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite á aplicación recibir e procesar mensaxes SMS. Isto significa que a aplicación pode supervisar ou eliminar mensaxes enviadas ao teu dispositivo sen mostrarchas."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recibir mensaxes de texto (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite á aplicación recibir e procesar mensaxes MMS. Isto significa que a aplicación pode supervisar ou eliminar mensaxes enviadas ao teu dispositivo sen mostrarchas."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Reenviar mensaxes de difusión móbil"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite que a aplicación se vincule ao módulo de difusión móbil para reenviar as mensaxes deste tipo segundo se reciban. As alertas de difusión móbil envíanse nalgunhas localizacións para avisar de situacións de emerxencia. As aplicacións maliciosas poden interferir no rendemento ou funcionamento do teu dispositivo cando se reciba unha difusión móbil de emerxencia."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ler mensaxes de difusión móbil"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite á aplicación ler mensaxes de difusión móbil recibidas polo teu dispositivo. As alertas de difusión móbil envíanse nalgunhas localizacións para avisar de situacións de emerxencia. É posible que aplicacións maliciosas afecten ao rendemento ou funcionamento do teu dispositivo cando se recibe unha difusión móbil de emerxencia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ler feeds subscritos"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permite á aplicación ler e escribir a configuración do modo Non molestar."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"iniciar uso de permiso de vista"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite ao propietario iniciar o uso de permisos dunha aplicación. As aplicacións normais non deberían precisalo nunca."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"obxectivo do atallo de accesibilidade"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite que unha aplicación defina o obxectivo do atallo de accesibilidade."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer as normas de contrasinal"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controla a lonxitude e os caracteres permitidos nos contrasinais e nos PIN de bloqueo da pantalla."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Controlar os intentos de desbloqueo da pantalla"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 340245a..05e5a4e 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"ઍપ્લિકેશનને SMS સંદેશા પ્રાપ્ત કરવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આનો અર્થ એ કે ઍપ્લિકેશન તમને દર્શાવ્યા વિના તમારા ઉપકરણ પર મોકલેલ સંદેશાઓનું નિરીક્ષણ કરી શકે છે અથવા કાઢી નાખી શકે છે."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ટેક્સ્ટ સંદેશા (MMS) પ્રાપ્ત કરો"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"ઍપ્લિકેશનને MMS સંદેશા પ્રાપ્ત કરવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આનો અર્થ એ કે ઍપ્લિકેશન તમને દર્શાવ્યા વિના તમારા ઉપકરણ પર મોકલેલ સંદેશાઓનું નિરીક્ષણ કરી શકે છે અથવા કાઢી નાખી શકે છે."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"સેલ બ્રોડકાસ્ટ સંદેશા ફૉરવર્ડ કરો"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"સેલ બ્રોડકાસ્ટ સંદેશા પ્રાપ્ત થાય કે તરત ફૉરવર્ડ કરવા માટે સેલ બ્રોડકાસ્ટ મૉડ્યૂલ સાથે પ્રતિબદ્ધ થવા બાબતે ઍપને મંજૂરી આપે છે. તમને કટોકટીની પરિસ્થિતિની ચેતવણી આપવા માટે સેલ બ્રોડકાસ્ટ અલર્ટ અમુક સ્થાનોમાં ડિલિવર કરવામાં આવે છે. કટોકટી અંગેનો સેલ બ્રોડકાસ્ટ પ્રાપ્ત થાય, ત્યારે દુર્ભાવનાપૂર્ણ ઍપ તમારા ડિવાઇસના કાર્યપ્રદર્શન અથવા ઑપરેશનમાં વિક્ષેપ પાડે તેમ બની શકે છે."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"સેલ બ્રોડકાસ્ટ સંદેશા વાંચો"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"એપ્લિકેશનને તમારા ઉપકરણ દ્વારા પ્રાપ્ત થયેલ સેલ બ્રોડકાસ્ટ સંદેશાને વાંચવાની મંજૂરી આપે છે. સેલ બ્રોડકાસ્ટ ચેતવણીઓ તમને કટોકટીની સ્થિતિઓ અંગે ચેતવવા માટે કેટલાક સ્થાનોમાં વિતરિત થાય છે. જ્યારે કટોકટીનો સેલ બ્રોડકાસ્ટ પ્રાપ્ત થાય ત્યારે દુર્ભાવનાપૂર્ણ ઍપ્લિકેશનો તમારા ઉપકરણના પ્રદર્શન અથવા ઓપરેશનમાં હસ્તક્ષેપ કરી શકે છે."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"સબ્સ્ક્રાઇબ કરેલ ફીડ્સ વાંચો"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"એપ્લિકેશનને ખલેલ પાડશો નહીં ગોઠવણી વાંચવા અને લખવાની મંજૂરી આપે છે."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"પરવાનગી વપરાશ જુઓને શરૂ કરો"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"કોઈ ઍપ માટે પરવાનગી વપરાશ શરૂ કરવાની ધારકને મંજૂરી આપે છે. સામાન્ય ઍપ માટે ક્યારેય જરૂર પડી ન શકે."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ઍક્સેસિબિલિટી શૉર્ટકટ ટાર્ગેટ"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ઍપને ઍક્સેસિબિલિટી શૉર્ટકટ ટાર્ગેટ વ્યાખ્યાતિત કરવાની મંજૂરી આપે છે."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"પાસવર્ડ નિયમો સેટ કરો"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"સ્ક્રીન લૉક પાસવર્ડ અને પિનમાં મંજૂર લંબાઈ અને અક્ષરોને નિયંત્રિત કરો."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"સ્ક્રીનને અનલૉક કરવાના પ્રયત્નોનું નિયમન કરો"</string>
@@ -1938,7 +1934,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"સમાચાર અને સામાયિકો"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"નકશા અને નેવિગેશન"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"ઉત્પાદકતા"</string>
-    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ઉપકરણ સ્ટૉરેજ"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ડિવાઇસ સ્ટૉરેજ"</string>
     <string name="adb_debugging_notification_channel_tv" msgid="5537766997350092316">"USB ડિબગિંગ"</string>
     <string name="time_picker_hour_label" msgid="2979075098868106450">"કલાક"</string>
     <string name="time_picker_minute_label" msgid="5168864173796598399">"મિનિટ"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 8f78f95..f16ad65 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -295,7 +295,7 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को एसएमएस (मैसेज) भेजने और देखने की अनुमति देना चाहते हैं?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"मेमोरी"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"अपने डिवाइस पर मौजूद फ़ोटो, मीडिया और फ़ाइलें ऐक्सेस करने की"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को डिवाइस पर मौजूद फ़ोटो, ऑडियो-वीडियो और फ़ाइलें ऐक्सेस करने की अनुमति दें?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को डिवाइस पर मौजूद फ़ोटो, ऑडियो-वीडियो, और फ़ाइलें ऐक्सेस करने की अनुमति दें?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"माइक्रोफ़ोन"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ऑडियो रिकॉर्ड करें"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को ऑडियो रिकॉर्ड करने की अनुमति देना चाहते हैं?"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"एप्लिकेशन को मैसेज (एसएमएस) पाने और प्रोसेस करने देता है. इसका मतलब है कि एप्लिकेशन आपके डिवाइस पर भेजे गए मैसेज की निगरानी आपको दिखाए बिना कर सकता है और उन्‍हें हटा सकता है."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"मैसेज (एमएमएस) पाएं"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"ऐप को मल्टीमीडिया मैसेज (एमएमएस) को पाने और उन पर कार्रवाई करने देता है. इसका मतलब है कि ऐप आपके डिवाइस पर भेजे गए मैसेज की निगरानी आपको दिखाए बिना कर सकता है और उन्‍हें हटा सकता है."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"सेल ब्रॉडकास्ट (CBC) मैसेज दूसरे नंबर पर भेजें"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"सेल ब्रॉडकास्ट (CBC) मैसेज आते ही उसे दूसरे नंबर पर भेजने के लिए, ऐप्लिकेशन को सेल ब्रॉडकास्ट (CBC) मॉड्यूल पर बाइंड करने की अनुमति देता है. कुछ जगहों में सेल ब्रॉडकास्ट (CBC) अलर्ट आपातकालीन स्थितियों के बारे में चेतावनी देने के लिए भेजा जाता है. नुकसान पहुंचाने वाले ऐप्लिकेशन, आपातकाल में सेल ब्रॉडकास्ट (CBC) मैसेज मिलने पर आपके डिवाइस के काम करते समय या इसके परफ़ॉर्मेंस में रुकावट पैदा कर सकते हैं."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ें"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ऐप को, वो सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ने देता है जो आपके डिवाइस को मिले हैं. सेल ब्रॉडकास्ट (CBC) अलर्ट कुछ स्थानों (लोकेशन) पर आपको आपातकालीन स्‍थितियों की चेतावनी देने के लिए दिए जाते हैं. आपातकालीन सेल ब्रॉडकास्ट (CBC) मिलने पर, धोखा देने वाले ऐप आपके डिवाइस के परफ़ॉर्मेंस या कार्यवाही में दखल दे सकते हैं."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"सदस्यता वाली फ़ीड पढ़ें"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"यह मंज़ूरी मिलने के बाद ऐप्लिकेशन जान पाता है कि स्क्रीन लॉक कितना मुश्किल (बहुत ज़्यादा, मध्यम, कम या बिल्कुल नहीं) है. इस स्तर से यह पता चलता है कि स्क्रीन लॉक कितना लंबा या किस तरह का है. ऐप्लिकेशन उपयोगकर्ताओं को यह सुझाव भी दे सकता है कि वे स्क्रीन लॉक को एक तय लेवल तक अपडेट करें. लेकिन उपयोगकर्ता इसे बेझिझक अनदेखा करके छोड़ सकते हैं. ध्यान दें कि स्क्रीन लॉक को सादे टेक्स्ट में सेव नहीं किया जाता है इसलिए ऐप्लिकेशन को सटीक पासवर्ड पता नहीं होता है."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"बायोमीट्रिक हार्डवेयर इस्तेमाल करने दें"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"पुष्टि के लिए, ऐप्लिकेशन को बायोमीट्रिक हार्डवेयर इस्तेमाल करने की मंज़ूरी दें"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"उंगली की छाप के लिए हार्डवेयर को प्रबंधित करें"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"उंगली की छाप वाले टेम्पलेट का उपयोग करने के लिए जोड़ने और हटाने के लिए ऐप को विधियां प्रारंभ करने देती है."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"उंगली की छाप के लिए हार्डवेयर का उपयोग करें"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ऐप के प्रमाणीकरण के लिए उंगली की छाप हार्डवेयर का उपयोग करने देती है"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"फ़िंगरप्रिंट हार्डवेयर को प्रबंधित करें"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"फ़िंगरप्रिंट वाले टेम्पलेट का इस्तेमाल करने के लिए जोड़ने और हटाने के लिए ऐप को तरीके शुरू करने देती है."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"फ़िंगरप्रिंट हार्डवेयर का उपयोग करें"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ऐप के प्रमाणीकरण के लिए फ़िंगरप्रिंट हार्डवेयर का उपयोग करने देती है"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"अपने संगीत संग्रह में बदलाव करने की अनुमति दें"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"इससे ऐप्लिकेशन को आपके संगीत संग्रह में बदलाव करने की मंज़ूरी दी जाती है"</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"अपने वीडियो संग्रह में बदलाव करने की अनुमति दें"</string>
@@ -534,7 +532,7 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"पहचान नहीं हो पाई"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"प्रमाणीकरण रद्द किया गया"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"पिन, पैटर्न या पासवर्ड सेट नहीं है"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक फ़िंगरप्रिंट की पहचान की गई. कृपया पुनः प्रयास करें."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"फ़िंगरप्रिंट की पहचान आंशिक तौर पर की गई. कृपया फिर से कोशिश करें."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"फ़िंगरप्रिंट प्रोसेस नहीं हो सका. कृपया दोबारा कोशिश करें."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"फ़िंगरप्रिंट सेंसर गंदा है. कृपया साफ़ करें और फिर कोशिश करें."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"उंगली बहुत तेज़ी से चलाई गई है. कृपया फिर से कोशिश करें."</string>
@@ -545,9 +543,9 @@
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"चेहरे की पहचान की गई"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"चेहरे की पहचान की गई, कृपया पुष्टि बटन दबाएं"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"फ़िंगरप्रिंट हार्डवेयर उपलब्ध नहीं है."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फ़िंगरप्रिंट को संग्रहित नहीं किया जा सका. कृपया कोई मौजूदा फ़िंगरप्रिंट निकालें."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फ़िंगरप्रिंट का समय खत्म हो गया. पुनः प्रयास करें."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"फ़िंगरप्रिंट क्रियान्वयन रोक दिया गया."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फ़िंगरप्रिंट को स्टोर नहीं किया जा सका. कृपया कोई मौजूदा फ़िंगरप्रिंट हटाएं."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फ़िंगरप्रिंट का समय खत्म हो गया. फिर से कोशिश करें."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"फ़िंगरप्रिंट ऑपरेशन रोक दिया गया."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"उपयोगकर्ता ने फिंगरप्रिंट की पुष्टि की कार्रवाई रद्द कर दी है."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"बहुत ज़्यादा प्रयास कर लिए गए हैं. बाद में फिर से प्रयास करें."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"बहुत ज़्यादा कोशिशें. फ़िंगरप्रिंट सेंसर अक्षम है."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"ऐप को परेशान न करें कॉन्फ़िगरेशन पढ़ने और लिखने देती है."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"देखने की अनुमतियां चालू करें"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"इस्तेमाल करने वाले को किसी ऐप्लिकेशन के लिए अनुमतियों का इस्तेमाल शुरू करने देता है. सामान्य ऐप्लिकेशन के लिए इसकी ज़रूरत कभी नहीं पड़ती."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"सुलभता शॉर्टकट टारगेट"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"सुलभता शॉर्टकट टारगेट के बारे में बताने के लिए ऐप्लिकेशन को मंज़ूरी दें."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियम सेट करना"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्‍क्रीन लॉक पासवर्ड और पिन की लंबाई और उनमें स्वीकृत वर्णों को नियंत्रित करना."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"स्‍क्रीन अनलॉक करने के की कोशिशों पर नज़र रखना"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 8ddd5f8..45c39f2 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -347,10 +347,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Aplikaciji omogućuje primanje i obradu SMS poruka. To znači da aplikacija može nadzirati ili izbrisati poruke poslane na vaš uređaj, a da vam ih ne prikaže."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"primanje tekstnih poruka (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Aplikaciji omogućuje primanje i obradu MMS poruka. To znači da aplikacija može nadzirati ili izbrisati poruke poslane na vaš uređaj, a da vam ih ne prikaže."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Prosljeđivanje poruka emitiranja na mobitele"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Omogućuje aplikaciji da se poveže s modulom za emitiranje na mobitele kako bi prosljeđivala poruke koje se emitiraju na mobitele po njihovom primitku. Upozorenja značajke emitiranja na mobitele dostavljaju se na nekim lokacijama kako bi upozorila korisnike na hitne situacije. Zlonamjerne aplikacije mogu ometati izvršavanje ili rad vašeg uređaja kada stigne hitno emitiranje na mobitele."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"čitaj poruke koje se emitiraju unutar mobilne mreže"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Omogućuje aplikaciji čitanje poruka emitiranih unutar mobilne mreže koje prima vaš uređaj. Upozorenja koja se emitiraju na području mobilne mreže dostavljaju se na nekim lokacijama kako bi upozorila korisnike na hitne situacije. Zlonamjerne aplikacije mogu ometati izvršavanje ili rad vašeg uređaja kada stigne hitno upozorenje koje se emitira unutar mobilne mreže."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čitanje pretplaćenih feedova"</string>
@@ -662,8 +660,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Omogućuje aplikaciji čitanje i pisanje konfiguracije opcije Ne ometaj."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"pokrenuti upotrebu dopuštenja za pregled"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Dopušta nositelju pokretanje upotrebe dopuštenja za aplikaciju. Ne bi smjelo biti potrebno za uobičajene aplikacije."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cilj prečaca pristupačnosti"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Aplikaciji omogućuje da definira cilj prečaca pristupačnosti."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Upravlja duljinom i znakovima koji su dopušteni u zaporkama i PIN-ovima zaključavanja zaslona."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Nadziri pokušaje otključavanja zaslona"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index d910025..aac2d76 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Lehetővé teszi az alkalmazás számára, hogy SMS-eket fogadjon és dolgozzon fel. Ez azt jelenti, hogy az alkalmazás megfigyelheti vagy törölheti a beérkező üzeneteket anélkül, hogy Ön látná azokat."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"szöveges üzenetek (MMS) fogadása"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Lehetővé teszi az alkalmazás számára, hogy MMS-eket fogadjon és dolgozzon fel. Ez azt jelenti, hogy az alkalmazás megfigyelheti vagy törölheti a beérkező üzeneteket anélkül, hogy Ön látná azokat."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Cellán belüli üzenetek továbbítása"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Az alkalmazás összekapcsolódhat a cellán belüli üzenetszórás moduljával, hogy az érkezésükkor továbbítani tudja a cellán belüli üzeneteket. Bizonyos helyeken figyelmeztető üzeneteket kaphat a cellán belül a vészhelyzetekről. A rosszindulatú alkalmazások vészhelyzeti cellaüzenet érkezésekor befolyásolhatják az eszköz teljesítményét és működését."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"cellán belüli üzenetek olvasása"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Lehetővé teszi az alkalmazás számára az eszközre érkező cellán belüli üzenetek olvasását. Bizonyos helyeken figyelmeztető üzeneteket kaphat a cellán belül a vészhelyzetekről. A rosszindulatú alkalmazások befolyásolhatják az eszköz  teljesítményét vagy működését vészhelyzeti cellaüzenet érkezésekor."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"feliratkozott hírcsatornák olvasása"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Az alkalmazás olvashatja és szerkesztheti a „Ne zavarjanak” funkció beállításait."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"engedélyhasználat megtekintésének elindítása"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Lehetővé teszi a felhasználó számára, hogy elindítsa az alkalmazás engedélyhasználatát. A normál alkalmazásoknak erre soha nincs szükségük."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"A kisegítő lehetőségek gyorsparancs célja"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Engedélyezi az alkalmazásoknak a kisegítő lehetőségek gyorsparancs céljának meghatározását."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"A képernyőzár jelszavaiban és PIN kódjaiban engedélyezett karakterek és hosszúság vezérlése."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Képernyőzár-feloldási kísérletek figyelése"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 6f5507f..a5b4e30 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -230,7 +230,7 @@
     <string name="global_action_bug_report" msgid="7934010578922304799">"Վրիպակի զեկույց"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Ավարտել աշխատաշրջանը"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"Սքրինշոթ"</string>
-    <string name="bugreport_title" msgid="5981047024855257269">"Վրիպակների զեկույց"</string>
+    <string name="bugreport_title" msgid="5981047024855257269">"Հաշվետվություն վրիպակի մասին"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Սա տեղեկություններ կհավաքագրի ձեր սարքի առկա կարգավիճակի մասին և կուղարկի այն էլեկտրոնային նամակով: Որոշակի ժամանակ կպահանջվի վրիպակի մասին զեկուցելու պահից սկսած մինչ ուղարկելը: Խնդրում ենք փոքր-ինչ համբերատար լինել:"</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Ինտերակտիվ զեկույց"</string>
     <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"Հիմնականում օգտագործեք այս տարբերակը: Այն ձեզ թույլ է տալիս հետևել զեկույցի ստեղծման գործընթացին, խնդրի մասին լրացուցիչ տեղեկություններ մուտքագրել և սքրինշոթներ ստեղծել: Կարող է բաց թողնել քիչ օգտագործվող որոշ բաժիններ, որոնց ստեղծումը երկար է տևում:"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Թույլ է տալիս հավելվածին ստանալ և մշակել SMS հաղորդագրությունները: Սա նշանակում է, որ հավելվածը կարող է ստուգել կամ ջնջել ձեր սարքին ուղարկված հաղորդագրությունները` առանց դրանք ձեզ ցուցադրելու:"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ստանալ տեքստային հաղորդագրություններ (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Թույլ է տալիս հավելվածին ստանալ և մշակել MMS հաղորդագրությունները: Սա նշանակում է, որ հավելվածը կարող է ստուգել կամ ջնջել ձեր սարքին ուղարկված հաղորդագրությունները` առանց դրանք ձեզ ցուցադրելու:"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Բջջային հեռարձակման հաղորդագրությունների վերահասցեավորում"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Թույլ է տալիս հավելվածին կապ հաստատել բջջային հեռարձակման մոդուլի հետ՝ բնակչությանը ծանուցող հաղորդագրությունները վերահասցեավորելու համար։ Որոշ երկրներում այս հաղորդագրություններն օգտագործվում են բնակչությանը արտակարգ իրավիճակների մասին զգուշացնելու համար: Վնասարար հավելվածները կարող են խանգարել ձեր սարքի աշխատանքին, որին ուղարկվում են այս հաղորդագրությունները:"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"կարդալ բջջային զեկուցվող հաղորդագրությունները"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Թույլ է տալիս հավելվածին կարդալ ձեր սարքի կողմից ստացված բջջային հեռարձակվող հաղորդագրությունները: Բջջային հեռարձակվող զգուշացումները ուղարկվում են որոշ վայրերում` արտակարգ իրավիճակների մասին ձեզ զգուշացնելու համար: Վնասարար հավելվածները կարող են խանգարել ձեր սարքի արդյունավետությանը կամ շահագործմանը, երբ ստացվում է արտակարգ իրավիճակի մասին բջջային հաղորդում:"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"կարդալ բաժանորդագրված հոսքերը"</string>
@@ -370,7 +368,7 @@
     <string name="permdesc_enableCarMode" msgid="4853187425751419467">"Թույլ է տալիս հավելվածին միացնել մեքենայի ռեժիմը:"</string>
     <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"փակել այլ հավելվածները"</string>
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Թույլ է տալիս հավելվածին վերջ տալ այլ հավելվածների հետնաշերտի գործընթացները: Սա կարող է պատճառ դառնալ, որ այլ հավելվածները դադարեն աշխատել:"</string>
-    <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Այս հավելվածը կարող է ցուցադրվել այլ հավելվածների վերևում"</string>
+    <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Այս հավելվածը կարող է ցուցադրվել այլ հավելվածների վրայից"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Այս հավելվածը կարող է ցուցադրվել այլ հավելվածների կամ էկրանի այլ հատվածների վերևում: Դա կարող է խոչընդոտել հավելվածի նորմալ օգտագործմանը և փոխել այլ հավելվածների տեսքը:"</string>
     <string name="permlab_runInBackground" msgid="7365290743781858803">"աշխատել ֆոնում"</string>
     <string name="permdesc_runInBackground" msgid="7370142232209999824">"Այս հավելվածը կարող է աշխատել ֆոնային ռեժիմում և ավելի արագ սպառել մարտկոցի լիցքը։"</string>
@@ -534,7 +532,7 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Չհաջողվեց ճանաչել"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Նույնականացումը չեղարկվեց"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Ավելացրեք PIN կոդ, նախշ կամ գաղտնաբառ։"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Մատնահետքը հայտնաբերվել է մասամբ: Փորձեք նորից:"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Մատնահետքն ամբողջությամբ չի սկանավորվել: Փորձեք նորից:"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Չհաջողվեց մշակել մատնահետքը: Նորից փորձեք:"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Մատնահետքերի սենսորն աղտոտված է: Մաքրեք այն և փորձեք նորից:"</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Շատ արագ անցկացրիք մատը: Փորձեք նորից:"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Թույլ է տալիս հավելվածին փոփոխել «Չանհանգստացնել» գործառույթի կազմաձևումը:"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"թույլտվությունների մասին տվյալների հասանելիություն"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Հավելվածին հասանելի կդառնան թույլտվությունների մասին տվյալները։ Այս թույլտվությունն անհրաժեշտ չէ սովորական հավելվածներին։"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"հատուկ գործառույթների դյուրանցումն օգտագործելու նպատակը"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Հավելվածին թույլ է տալիս որոշել հատուկ գործառույթների դյուրանցումն օգտագործելու նպատակը։"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Սահմանել գաղտնաբառի կանոնները"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Կառավարել էկրանի ապակողպման գաղտնաբառերի և PIN կոդերի թույլատրելի երկարությունն ու գրանշանները:"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Վերահսկել էկրանի ապակողպման փորձերը"</string>
@@ -1387,8 +1383,8 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՈՒՓՔԵւՕՖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"Ցուցադրում այլ հավելվածների վրայից"</string>
-    <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վերևում"</string>
-    <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վերևում"</string>
+    <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վրայից"</string>
+    <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վրայից"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Եթե չեք ցանկանում, որ <xliff:g id="NAME">%s</xliff:g>-ն օգտագործի այս գործառույթը, հպեք՝ կարգավորումները բացելու և այն անջատելու համար։"</string>
     <string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"Անջատել"</string>
     <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"<xliff:g id="NAME">%s</xliff:g> հիշասարքի ստուգում…"</string>
@@ -1555,7 +1551,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Ավելի շատ ընտրանքներ"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Համօգտագործվող ներքին հիշողություն"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Ներքին ընդհանուր կրիչ"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD քարտ"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"SD քարտ <xliff:g id="MANUFACTURER">%s</xliff:g>-ից"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"USB սարքավար"</string>
@@ -1588,7 +1584,7 @@
     <string name="serial_number" msgid="758814067660862493">"Հերթական համարը`"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Մատնահետքերը`"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 մատնահետք`"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1մատնահետք`"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 մատնահետք`"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Տեսնել բոլորը"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Ընտրել գործունեությունը"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Կիսվել"</string>
@@ -2011,7 +2007,7 @@
     <string name="standby_warning_message" product="default" msgid="5222741828239073484">"Սարքը շուտով կանջատվի: Սեղմեք՝ միացրած թողնելու համար:"</string>
     <string name="notification_appops_camera_active" msgid="5050283058419699771">"Տեսախցիկ"</string>
     <string name="notification_appops_microphone_active" msgid="4335305527588191730">"Խոսափող"</string>
-    <string name="notification_appops_overlay_active" msgid="633813008357934729">"ցուցադրվում է մյուս հավելվածների վերևում"</string>
+    <string name="notification_appops_overlay_active" msgid="633813008357934729">"ցուցադրվում է մյուս հավելվածների վրայից"</string>
     <string name="dynamic_mode_notification_channel_name" msgid="2348803891571320452">"Ծանուցում լիցքավորման մասին"</string>
     <string name="dynamic_mode_notification_title" msgid="508815255807182035">"Մարտկոցի լիցքը կարող է սովորականից շուտ սպառվել"</string>
     <string name="dynamic_mode_notification_summary" msgid="2541166298550402690">"Մարտկոցի կյանքը երկարացնելու համար ակտիվացվել է մարտկոցի տնտեսման ռեժիմը"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 88e396c..228da88 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -161,7 +161,7 @@
     <string name="httpErrorProxyAuth" msgid="1788207010559081331">"Autentikasi via proxy server gagal."</string>
     <string name="httpErrorConnect" msgid="8714273236364640549">"Tidak dapat tersambung ke server."</string>
     <string name="httpErrorIO" msgid="2340558197489302188">"Tidak dapat berkomunikasi dengan server. Coba lagi nanti."</string>
-    <string name="httpErrorTimeout" msgid="4743403703762883954">"Sambungan ke server terputus."</string>
+    <string name="httpErrorTimeout" msgid="4743403703762883954">"Koneksi ke server terputus."</string>
     <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"Halaman ini berisi terlalu banyak pengalihan server."</string>
     <string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"Protokol tidak didukung."</string>
     <string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"Tidak dapat membuat sambungan aman."</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Memungkinkan aplikasi menerima dan memproses pesan SMS. Ini artinya aplikasi dapat memantau atau menghapus pesan yang dikirim ke perangkat Anda tanpa menunjukkannya kepada Anda."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"terima pesan teks (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Memungkinkan aplikasi menerima dan memproses pesan MMS. Ini artinya aplikasi dapat memantau atau menghapus pesan yang dikirim ke perangkat Anda tanpa menunjukkannya kepada Anda."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Teruskan pesan cell broadcast"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Mengizinkan aplikasi mem-binding ke modul cell broadcast untuk meneruskan pesan cell broadcast saat pesan tersebut diterima. Notifikasi cell broadcast dikirim di beberapa lokasi untuk memperingatkan Anda tentang situasi darurat. Aplikasi berbahaya dapat mengganggu performa atau operasi perangkat saat cell broadcast darurat diterima."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"membaca pesan siaran seluler"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Mengizinkan aplikasi membaca pesan siaran seluler yang diterima perangkat Anda. Notifikasi siaran seluler dikirimkan di beberapa lokasi untuk memperingatkan Anda tentang situasi darurat. Aplikasi berbahaya dapat mengganggu kinerja atau operasi perangkat Anda saat siaran seluler darurat diterima."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"baca feed langganan"</string>
@@ -519,7 +517,7 @@
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"kelola hardware sidik jari"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Mengizinkan aplikasi memanggil metode untuk menambahkan dan menghapus template sidik jari untuk digunakan."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"gunakan hardware sidik jari"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Mengizinkan aplikasi untuk menggunakan hardware sidik jari untuk otentikasi"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Mengizinkan aplikasi untuk menggunakan hardware sidik jari untuk autentikasi"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"memodifikasi koleksi musik Anda"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Mengizinkan aplikasi untuk memodifikasi koleksi musik Anda."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"memodifikasi koleksi video Anda"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Mengizinkan aplikasi membaca dan menulis konfigurasi status Jangan Ganggu."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"mulai melihat penggunaan izin"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Memungkinkan pemegang memulai penggunaan izin untuk aplikasi. Tidak diperlukan untuk aplikasi normal."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"target pintasan aksesibilitas"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Mengizinkan aplikasi menentukan target pintasan aksesibilitas."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setel aturan sandi"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Mengontrol panjang dan karakter yang diizinkan dalam sandi dan PIN kunci layar."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Pantau upaya pembukaan kunci layar"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 32461d3..d0f8028 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Leyfir forriti að taka á móti og vinna úr SMS-skilaboðum. Þetta þýðir að forritið getur fylgst með eða eytt skilaboðum sem send eru í tækið án þess að birta þér þau."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"taka á móti textaskilaboðum (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Leyfir forriti að taka á móti og vinna úr MMS-skilaboðum. Þetta þýðir að forritið getur fylgst með eða eytt skilaboðum sem send eru í tækið án þess að birta þér þau."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Framsenda skilaboð frá endurvarpa"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Heimilar forritinu að bindast endurvarpseiningunni til að framsenda skilaboð frá endurvarpa þegar þau berast. Viðvaranir frá endurvarpa berast á tilteknum stöðum til að vara þig við neyðarástandi. Spilliforrit geta truflað afköst eða virkni tækisins þegar neyðarboð berast frá endurvarpa."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lesa skilaboð frá endurvarpa"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Leyfir forriti að lesa skilaboð frá endurvarpa sem tækið móttekur. Viðvaranir frá endurvarpa berast á tilteknum stöðum til að vara þig við neyðarástandi. Spilliforrit geta truflað afköst eða virkni tækisins þegar neyðarboð berast frá endurvarpa."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lesa strauma í áskrift"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Leyfir forriti að lesa og skrifa í grunnstillingu „Ónáðið ekki“."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"heimildanotkun upphafsyfirlits"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Leyfir handhafa að byrja heimildanotkun fyrir forrit. Ætti aldrei að þurfa fyrir venjuleg forrit."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"áfangastaður aðgengisflýtileiðar"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Leyfir forriti að skilgreina áfangastað aðgengisflýtileiðar."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setja reglur um aðgangsorð"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Stjórna lengd og fjölda stafa í aðgangsorðum og PIN-númerum skjáláss."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Fylgjast með tilraunum til að taka skjáinn úr lás"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 6e25563..747d918 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -344,12 +344,10 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Consente all\'applicazione di ricevere ed elaborare messaggi SMS. Significa che l\'applicazione potrebbe monitorare o eliminare i messaggi inviati al tuo dispositivo senza mostrarteli."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ricezione messaggi di testo (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Consente all\'applicazione di ricevere ed elaborare messaggi MMS. Significa che l\'applicazione potrebbe monitorare o eliminare i messaggi inviati al tuo dispositivo senza mostrarteli."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Inoltro di messaggi cell broadcast"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Consente all\'app di essere associata al modulo di cell broadcast al fine di inoltrare i messaggi di cell broadcast man mano che arrivano. Gli avvisi cell broadcast vengono trasmessi in alcune località per avvertire di situazioni di emergenza. Le app dannose potrebbero interferire con le prestazioni o con il funzionamento del dispositivo quando si riceve un messaggio cell broadcast di emergenza."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lettura di messaggi cell broadcast"</string>
-    <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Consente all\'applicazione di leggere i messaggi cell broadcast ricevuti dal dispositivo. Gli avvisi cell broadcast vengono trasmessi in alcune località per avvertire di eventuali situazioni di emergenza. Le applicazioni dannose potrebbero interferire con il rendimento o con il funzionamento del dispositivo quando si riceve un messaggio cell broadcast di emergenza."</string>
+    <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Consente all\'applicazione di leggere i messaggi cell broadcast ricevuti dal dispositivo. Gli avvisi cell broadcast vengono trasmessi in alcune località per avvertire di eventuali situazioni di emergenza. Le app dannose potrebbero interferire con le prestazioni o con il funzionamento del dispositivo quando si riceve un messaggio cell broadcast di emergenza."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lettura feed sottoscritti"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Consente all\'applicazione di ottenere dettagli sui feed attualmente sincronizzati."</string>
     <string name="permlab_sendSms" msgid="7544599214260982981">"invio e visualizzazione di SMS"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Consente all\'app di leggere e modificare la configurazione della funzione Non disturbare."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"avvio dell\'uso dell\'autorizzazione di visualizzazione"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Consente al titolare di avviare l\'uso delle autorizzazioni per un\'app. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"target della scorciatoia Accessibilità"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Consente a un\'app di definire il target della scorciatoia Accessibilità"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Impostare regole per le password"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controlla la lunghezza e i caratteri ammessi nelle password e nei PIN del blocco schermo."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitorare tentativi di sblocco dello schermo"</string>
@@ -1588,7 +1584,7 @@
     <string name="serial_number" msgid="758814067660862493">"Numero di serie:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Fingerprint:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"Impronta SHA-256:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"Impronta SHA-1:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Fingerprint SHA-1:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Mostra tutto"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Scegli attività"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Condividi con"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 6e61213..4c12e43 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -330,7 +330,7 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"קבע את המרחק מהתצוגה ואת מיקום התצוגה."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ביצוע תנועות"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"יכול להקיש, להחליק, לעשות תנועת צביטה ולבצע תנועות אחרות."</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"תנועות"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"תנועות של טביעות אצבעות"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"אפשרות לזהות תנועות בזמן נגיעה בחיישן טביעות האצבע של המכשיר."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"השבת או שנה את שורת המצב"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"מאפשר לאפליקציה להשבית את שורת המצב או להוסיף ולהסיר סמלי מערכת."</string>
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"‏מאפשר לאפליקציה לקבל ולעבד הודעות SMS. משמעות הדבר היא שהאפליקציה יכולה לעקוב אחר הודעות שנשלחו למכשיר או למחוק אותן מבלי להציג לך אותן."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"‏קבלת הודעות טקסט (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"‏מאפשר לאפליקציה לקבל ולעבד הודעות MMS. משמעות הדבר היא שהאפליקציה יכולה לעקוב אחר הודעות שנשלחו למכשיר או למחוק אותן מבלי להציג לך אותן."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"העברת הודעות של שידור סלולרי"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"מאפשרת לאפליקציה להתחייב למודול של השידור הסלולרי כדי להעביר הודעות של שידור סלולרי כשהן מתקבלות. התראות שידור סלולרי נשלחות במקומות מסוימים כדי להזהיר אותך מפני מצבי חירום. אפליקציות זדוניות עשויות להפריע לביצועים או לפעולה של המכשיר כאשר מתקבל שידור חירום סלולרי."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"קריאת הודעות שידור סלולרי"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"מאפשר לאפליקציה לקרוא הודעות שידור סלולרי שהתקבלו במכשיר שלך. התראות שידור סלולרי נשלחות במקומות מסוימים על מנת להזהיר אותך מפני מצבי חירום. אפליקציות זדוניות עשויות להפריע לביצועים או לפעולה של המכשיר שלך כאשר מתקבל שידור חירום סלולרי."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"קרא עדכוני מנויים"</string>
@@ -540,9 +538,9 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"לא זוהתה"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"האימות בוטל"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"עוד לא הוגדרו קוד גישה, קו ביטול נעילה או סיסמה"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"זוהתה טביעת אצבע חלקית. נסה שוב."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"זוהתה טביעת אצבע חלקית. אפשר לנסות שוב."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"לא ניתן היה לעבד את טביעת האצבע. נסה שוב."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"החיישן של טביעות האצבעות מלוכלך. נקה אותו ונסה שוב."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"החיישן של טביעות האצבעות מלוכלך. צריך לנקות אותו ולנסות שוב."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"הזזת את האצבע מהר מדי. נסה שוב."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"הזזת את האצבע לאט מדי. נסה שוב."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -550,9 +548,9 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"טביעת האצבע אומתה"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"זיהוי הפנים בוצע"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"זיהוי הפנים בוצע. יש ללחוץ על אישור"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"החומרה בשביל טביעת אצבע אינה זמינה."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"לא ניתן לאחסן טביעת אצבע. הסר טביעת אצבע קיימת."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"חלף הזמן הקצוב לטביעת אצבע. נסה שוב."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"החומרה בשביל טביעות אצבעות אינה זמינה."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"לא ניתן לאחסן טביעת אצבע. יש להסיר טביעת אצבע קיימת."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"חלף הזמן הקצוב לטביעת אצבע. אפשר לנסות שוב."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"פעולת טביעת האצבע בוטלה."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"פעולת טביעת האצבע בוטלה בידי המשתמש."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"יותר מדי ניסיונות. נסה שוב מאוחר יותר."</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"מאפשר לאפליקציה לקרוא ולכתוב את התצורה של \'נא לא להפריע\'."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"התחלת צפייה בהרשאות השימוש"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"מאפשרת לבעלים להפעיל את השימוש בהרשאות עבור אפליקציה מסוימת. הרשאה זו אף פעם לא נדרשת עבור אפליקציות רגילות."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"קיצור דרך ליעד של פעולת נגישות"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"מאפשרת לאפליקציה להגדיר את קיצור הדרך ליעד של פעולת נגישות."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"הגדר כללי סיסמה"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"קביעת האורך הנדרש והתווים המותרים בסיסמאות ובקודי הגישה של מסך הנעילה."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"מעקב אחר ניסיונות לביטול של נעילת המסך"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 15e10e4..98600b8 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMSメッセージの受信と処理をアプリに許可します。これにより、アプリがデバイスに届いたメッセージを表示することなく監視または削除できるようになります。"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"テキストメッセージ(MMS)の受信"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMSメッセージの受信と処理をアプリに許可します。これにより、アプリがデバイスに届いたメッセージを表示することなく監視または削除できるようになります。"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"緊急速報メールの転送"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"受信した緊急速報メールを転送するために、緊急速報メール モジュールにバインドすることをこのアプリに許可します。緊急速報メールは、緊急事態を警告する目的で一部の地域に配信されます。緊急速報メールの受信時に、悪意のあるアプリによってデバイスの動作や処理が妨害される恐れがあります。"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"緊急速報メール SMS の読み取り"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"デバイスで受信した緊急速報メール SMS の読み取りをアプリに許可します。緊急速報メールは、緊急事態を警告する目的で一部の地域に配信されます。緊急速報メールの受信時に、悪意のあるアプリによってデバイスの動作や処理が妨害される恐れがあります。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"登録したフィードの読み取り"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"サイレント モード設定の読み取りと書き込みをアプリに許可します。"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"表示権限の使用の開始"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"アプリの権限使用の開始を所有者に許可します。通常のアプリでは不要です。"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ユーザー補助ショートカットのターゲット"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ユーザー補助ショートカットのターゲットの定義付けをアプリに許可します。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードルールの設定"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"画面ロックのパスワードとPINの長さと使用できる文字を制御します。"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"画面ロック解除試行の監視"</string>
@@ -1195,7 +1191,7 @@
     <string name="unsupported_display_size_show" msgid="7969129195360353041">"常に表示"</string>
     <string name="unsupported_compile_sdk_message" msgid="4253168368781441759">"<xliff:g id="APP_NAME">%1$s</xliff:g> は、互換性のない Android OS バージョン用にビルドされているため、予期しない動作が発生するおそれがあります。アプリの更新バージョンを利用できる場合があります。"</string>
     <string name="unsupported_compile_sdk_show" msgid="2681877855260970231">"常に表示"</string>
-    <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"アップデートをチェック"</string>
+    <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"アップデートを確認"</string>
     <string name="smv_application" msgid="3307209192155442829">"アプリ「<xliff:g id="APPLICATION">%1$s</xliff:g>」(プロセス「<xliff:g id="PROCESS">%2$s</xliff:g>」)でStrictModeポリシー違反がありました。"</string>
     <string name="smv_process" msgid="5120397012047462446">"プロセス<xliff:g id="PROCESS">%1$s</xliff:g>でStrictModeポリシー違反がありました。"</string>
     <string name="android_upgrading_title" product="default" msgid="7513829952443484438">"スマートフォンの更新中…"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index a66d897..cc8ecc2 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"აპს შეეძლება SMS შეტყობინებების მიღება და დამუშავება. ეს ნიშნავს, რომ აპს შეეძლება თქვენ მოწყობილობაზე გამოგზავნილი შეტყობინებების მონიტორინგი და მათი წაშლა თქვენთვის ჩვენების გარეშე."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ტექსტური შეტყობინებების (MMS) მიღება"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"აპს შეეძლება MMS შეტყობინებების მიღება და დამუშავება. ეს ნიშნავს, რომ აპს შეეძლება შეტყობინებების მონიტორინგი და მათი წაშლა თქვენთვის ჩვენების გარეშე."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Cell broadcast შეტყობინებების გადამისამართება"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"საშუალებას აძლევს აპს, დაუკავშირდეს cell broadcast მოდულს იმისთვის, რომ გადაამისამართოს cell broadcast შეტყობინებები მათი მიღებისთანავე. Cell broadcast გაფრთხილებები მიეწოდება ზოგიერთ მდებარეობაზე საგანგებო სიტუაციების შესახებ გაფრთხილების მიზნით. საგანგებო cell broadcast-ის მიღების დროს, მავნე აპებმა შეიძლება ხელი შეუშალონ თქვენი მოწყობილობის ფუნქციონირებას ან ოპერაციებს."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"მასიური დაგზავნის შეტყობინებების წაკითხვა"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"აპს შეეძლება, წაიკითხოს თქვენს მოწყობილობაზე გამოგზავნილი ქსელის სამაუწყებლო შეტყობინებები. სამაუწყებლო გაფრთხილებები მოგეწოდებათ ზოგიერთ ადგილზე ექსტრემალური სიტუაციების შესახებ გასაფრთხილებლად. ქსელის გადაუდებელი შეტყონიბენის მიღების დროს მავნე აპებმა შეიძლება ხელი შეუშალონ თქვენი მოწყობილობის ფუნქციონირებას ან ოპერაციებს."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"გამოწერილი არხების წაკითხვა"</string>
@@ -517,9 +515,9 @@
     <string name="permlab_useBiometric" msgid="8837753668509919318">"ბიომეტრიული აპარატის გამოყენება"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"საშუალებას აძლევს აპს, ავტორიზაციისთვის გამოიყენოს ბიომეტრიული აპარატი"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"თითის ანაბეჭდის აპარატის მართვა"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"საშუალებას აძლევს აპლიკაციას დაამატოს ან ამოშალოს გამოსაყენებელი თითის ანაბეჭდის ნიმუშები,"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"საშუალებას აძლევს აპლიკაციას დაამატოს ან ამოშალოს გამოსაყენებელი თითის ანაბეჭდის ნიმუშები."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"თითის ანაბეჭდის აპარატის გამოყენება"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"საშუალებას აძლევს აპლიკაციას გამოიყენოს ავტენთიფიკაციისათვის თითის ანაბეჭდის აპარატი"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"საშუალებას აძლევს აპლიკაციას ავტორიზაციისთვის გამოიყენოს თითის ანაბეჭდის აპარატი"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"თქვენი მუსიკალური კოლექციის შეცვლა"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"აპი შეძლებს თქვენი მუსიკალური კოლექციის შეცვლას."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"თქვენი ვიდეოკოლექციის შეცვლა"</string>
@@ -535,7 +533,7 @@
     <string name="biometric_error_canceled" msgid="349665227864885880">"ავტორიზაცია გაუქმდა"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"PIN-კოდი, ნიმუში ან პაროლი დაყენებული არ არის"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"აღმოჩენილია თითის ნაწილობრივი ანაბეჭდი. გთხოვთ, სცადოთ ხელახლა."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"თითის ანაბეჭდი ვერ მუშავდება. გთხოვთ, სცადოთ ხელახლა."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"თითის ანაბეჭდის დამუშავება ვერ მოხერხდა. გთხოვთ, ცადოთ ხელახლა."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"თითის ანაბეჭდის სენსორი დაბინძურებულია. გთხოვთ, გაასუფთაოთ და სცადოთ ხელახლა."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"თითის აღება მეტისმეტად სწრაფად მოხდა. გთხოვთ, სცადოთ ხელახლა."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"თითის აღება მეტისმეტად ნელა მოხდა. გთხოვთ, სცადოთ ხელახლა."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"საშუალებას აძლევს აპს, წაიკითხოს და დაწეროს კონფიგურაცია „არ შემაწუხოთ“."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"ნახვის ნებართვის გამოყენების დაწყება"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"მფლობელს საშუალებას აძლევს, დაიწყოს აპის ნებართვის გამოყენება. ჩვეულებრივი აპებისთვის არასოდეს უნდა იყოს საჭირო."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"მარტივი წვდომის მალსახმობის სამიზნე"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"აპს აძლევს მარტივი წვდომის მალსახმობის სამიზნის განსაზღვრის საშუალებას."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"პაროლის წესების დაყენება"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"აკონტროლეთ ეკრანის ბლოკირების პაროლებისა და PIN-ების სიმბოლოების სიგრძე."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"ეკრანის განბლოკვის მცდელობების მონიტორინგი"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index af6b788..db9fad2 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Қолданбаға SMS хабарларын алу және өңдеу мүмкіндігін береді. Бұл қолданба құрылғыңызға жіберілген хабарларды сізге көрсетпестен қабылдай және жоя алады дегенді білдіреді."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"мәтін хабарларын алу (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Қолданбаға MMS хабарларын алу және өңдеу мүмкіндігін береді. Бұл қолданба құрылғыңызға жіберілген хабарларды сізге көрсетпестен қабылдай және жоя алады дегенді білдіреді."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Ұялы таратылым хабарларының бағытын өзгерту"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Ұялы таратылым хабарлары алынғаннан кейін, олардың бағытын өзгерту үшін қолданбаға ұялы таратылым модулімен байланыстыруға мүмкіндік береді. Ұялы таратылым ескертулері кей аймақтарда төтенше жағдайлар туралы хабарлау үшін беріледі. Төтенше жағдай туралы ұялы таратылым хабары алынғаннан кейін, зиянды қолданбалар құрылғы жұмысына кедергі келтіруі мүмкін."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ұялы хабар тарату хабарларын оқу"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Қолданбаға ұялы таратылым хабарларын оқу мүмкіндігін береді. Ұялы таратылым дабылдары кейбір аймақтарда төтенше жағдай туралы ескерту үшін қолданылады. Төтенше ұялы хабарлар келгенде залалды қолданбалар құрылғының жұмысына кедергі жасауы мүмкін."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"жазылған ағындарды оқу"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Қолданбаға «Мазаламау» конфигурациясын оқу және жазу мүмкіндігін береді."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"рұқсаттарды пайдалану туралы деректерді көру"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Пайдаланушы қолданбаға берілетін рұқсаттарды басқара алады. Ондай рұқсаттар әдеттегі қолданбаларға керек емес."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"арнайы мүмкіндіктер таңбашасының мақсаты"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Қолданбаға арнайы мүмкіндіктер таңбашасының мақсатын анықтауға мүмкіндік береді."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Құпия сөз ережелерін тағайындау"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Экран бекітпесінің құпия сөздерінің және PIN кодтарының ұзындығын және оларда рұқсат етілген таңбаларды басқару."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Экран құлпын ашу әркеттерін бақылау"</string>
@@ -1556,7 +1552,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Басқа опциялар"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Ішкі ортақ қойма"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Ішкі ортақ жад"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD картасы"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD картасы"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"USB дискі"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index cf9b9d2..021da3e 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -325,7 +325,7 @@
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ធ្វើកាយវិការ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"អាចប៉ះ អូស ច្បិច និងធ្វើកាយវិការផ្សេងទៀត"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ចលនា​ស្នាមម្រាមដៃ"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"អាចថត​ចលនា​ដែលមាន​សកម្មភាព​នៅលើ​ឧបករណ៍​ចាប់​ស្នាម​ម្រាមដៃ​របស់ឧបករណ៍បាន។"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"អាចចាប់យក​ចលនា​ដែលធ្វើនៅលើ​នៅលើ​ឧបករណ៍​ចាប់​ស្នាម​ម្រាមដៃ​របស់ឧបករណ៍បាន។"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"បិទ ឬ​កែ​របារ​ស្ថានភាព"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"ឲ្យ​កម្មវិធី​បិទ​របារ​ស្ថានភាព ឬ​បន្ថែម និង​លុប​រូប​តំណាង​ប្រព័ន្ធ។"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ធ្វើជារបារស្ថានភាព"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"ឲ្យ​កម្មវិធី​ទទួល និង​ដំណើរការ​​សារ MMS ។ មាន​ន័យ​ថា កម្មវិធី​អាច​ត្រួតពិនិត្យ​ ឬ​លុប​សារ​ដែល​បាន​ផ្ញើ​ទៅ​ឧបករណ៍​របស់​អ្នក ដោយ​​មិន​បង្ហាញ​អ្នក។"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ទទួល​សារ​អត្ថបទ (MMS​)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"ឲ្យ​កម្មវិធី​ទទួល និង​ដំណើរការ​​សារ​ MMS ។ វា​មាន​ន័យ​ថា កម្មវិធី​អាច​តាមដាន​ ឬ​លុប​សារ​ដែល​បាន​ផ្ញើ​ទៅ​ឧបករណ៍​របស់​អ្នក​ដោយ​មិន​បង្ហាញ​ពួកវា។"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"បញ្ជូន​សារ​ផ្សាយចល័ត​បន្ត"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"អនុញ្ញាតឱ្យ​កម្មវិធី​ភ្ជាប់ទៅ​ម៉ូឌុល​ការផ្សាយចល័ត ដើម្បីបញ្ជូន​សារផ្សាយ​ចល័តបន្ត នៅពេល​ទទួលបាន​សារទាំងនោះ។ ការជូនដំណឹងអំពី​ការផ្សាយចល័ត​ត្រូវបានបញ្ជូនទៅ​ទីតាំងមួយចំនួន ដើម្បីព្រមាន​អ្នក​អំពីស្ថានភាព​អាសន្ន។ កម្មវិធី​គ្រោះថ្នាក់​អាច​រំខាន​ដល់ដំណើរការ ឬប្រតិបត្តិការ​ឧបករណ៍​របស់អ្នក នៅពេល​ទទួលបានការផ្សាយ​ចល័តពេលមានអាសន្ន​។"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"អាន​សារ​ប្រកាស​ចល័ត"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ឲ្យ​កម្មវិធី​អាន​សារ​ប្រកាស​ការ​ហៅ​ដែល​ឧបករណ៍​របស់​​អ្នក​បាន​ទទួល។ ការ​ជូន​ដំណឹង​ប្រកាស​ចល័ត​ត្រូវ​បាន​បញ្ជូន​ទៅ​ទីតាំង​មួយ​ចំនួន ដើម្បី​ព្រមាន​អ្នក​អំពី​ស្ថានភាព​អាសន្ន។ កម្មវិធី​ព្យាបាទ​អាច​ជ្រៀតជ្រែក​ការ​អនុវត្ត ឬ​ប្រតិបត្តិការ​ឧបករណ៍​របស់​អ្នក​​ពេល​ទទួល​ការ​ប្រកាស​ចល័ត​ពេល​អាសន្ន។"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"អាន​អត្ថបទ​ព័ត៌មាន​បាន​ជាវ"</string>
@@ -517,7 +515,7 @@
     <string name="permlab_useBiometric" msgid="8837753668509919318">"ប្រើ​ឧបករណ៍​ស្កេន​ស្នាមម្រាមដៃ"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"អនុញ្ញាត​ឱ្យ​កម្មវិធី​ប្រើ​ឧបករណ៍​ស្កេន​ស្នាមម្រាមដៃ​សម្រាប់​ការផ្ទៀងផ្ទាត់"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"គ្រប់គ្រងផ្នែករឹងស្នាមម្រាមដៃ"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"អនុញ្ញាតឲ្យកម្មវិធីប្រើវិធីសាស្ត្របន្ថែម និងលុបពុម្ពម្រាមដៃសម្រាប់ប្រើប្រាស់។"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"អនុញ្ញាតឲ្យកម្មវិធីប្រើវិធីនានា ដើម្បីបញ្ចូល និងលុបទម្រង់គំរូស្នាមម្រាមដៃសម្រាប់ប្រើប្រាស់។"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ប្រើផ្នែករឹងស្នាមម្រាមដៃ"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"អនុញ្ញាតឲ្យកម្មវិធីប្រើផ្នែករឹងស្នាមម្រាមដៃសម្រាប់ការផ្ទៀងផ្ទាត់"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"កែប្រែ​បណ្ដុំ​តន្ត្រី​របស់​អ្នក"</string>
@@ -536,7 +534,7 @@
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"គ្មាន​ការកំណត់​កូដ pin លំនាំ ឬពាក្យសម្ងាត់​ទេ"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"បានផ្តិតយកស្នាមម្រាមដៃមិនពេញលក្ខណៈ។ សូមព្យាយាមម្តងទៀត។"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"មិនអាចដំណើរការស្នាមម្រាមដៃបានទេ។ សូមព្យាយាមម្តងទៀត។"</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ឧបករណ៍ផ្តិតម្រាមដៃប្រឡាក់ហើយ។ សូមសម្អាត ហើយព្យាយាមម្តងទៀត។"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ឧបករណ៍ចាប់ស្នាមម្រាមដៃគឺប្រឡាក់។ សូមសម្អាត រួចព្យាយាមម្តងទៀត។"</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"ម្រាមដៃផ្លាស់ទីលឿនពេក។ សូមព្យាយាមម្តងទៀត។"</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ចលនាម្រាមដៃយឺតពេកហើយ។ សូមព្យាយាមម្តងទៀត។"</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -546,7 +544,7 @@
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"បានផ្ទៀងផ្ទាត់​មុខ សូម​ចុច​បញ្ជាក់"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ផ្នែករឹងស្នាមម្រាមដៃមិនមានទេ។"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"មិនអាចផ្ទុកស្នាមម្រាមដៃទេ។ សូមយកស្នាមម្រាមដៃដែលមានស្រាប់ចេញ។"</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ការផ្តិតម្រាមដៃបានអស់ពេល។ សូមព្យាយាមម្តងទៀត។"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ស្នាមម្រាមដៃបានអស់ម៉ោង។ សូមព្យាយាមម្តងទៀត។"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"បានបោះបង់ប្រតិបត្តិការស្នាមម្រាមដៃ។"</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ប្រតិបត្តិការ​ស្នាម​ម្រាម​ដៃ​ត្រូវ​បាន​បោះ​បង់​ដោយ​អ្នក​ប្រើប្រាស់។"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ព្យាយាមចូលច្រើនពេកហើយ។ សូមព្យាយាមម្តងទៀតពេលក្រោយ។"</string>
@@ -557,7 +555,7 @@
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ម្រាមដៃ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"រូបតំណាងស្នាមម្រាមដៃ"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"រូបស្នាមម្រាមដៃ"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"គ្រប់គ្រង​ហាតវែរ​ដោះសោតាមទម្រង់មុខ"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"អនុញ្ញាតឱ្យកម្មវិធីប្រើវិធីសាស្ត្រដើម្បី​បញ្ចូល និងលុបទម្រង់​គំរូ​ផ្ទៃមុខសម្រាប់ប្រើប្រាស់។"</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"ប្រើ​ហាតវែរ​ដោះសោ​តាមទម្រង់មុខ"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"អនុញ្ញាតឲ្យកម្មវិធីអាន និងសរសេរការកំណត់រចនាសម្ព័ន្ធមុខងារ កុំរំខាន។"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"ចាប់ផ្ដើម​មើល​ការប្រើប្រាស់​ការអនុញ្ញាត"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"អនុញ្ញាត​ឱ្យម្ចាស់​ចាប់ផ្ដើម​ការប្រើប្រាស់​ការអនុញ្ញាត​សម្រាប់កម្មវិធី។ មិនគួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"គោលដៅផ្លូវកាត់ភាពងាយស្រួល"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"អនុញ្ញាតឱ្យ​កម្មវិធី​កំណត់​គោលដៅ​ផ្លូវកាត់​ភាពងាយស្រួល។"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"កំណត់​ក្បួន​ពាក្យ​សម្ងាត់"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"គ្រប់គ្រងប្រវែង និងតួអក្សរដែលអនុញ្ញាតឲ្យប្រើក្នុងពាក្យសម្ងាត់ និងលេខសម្ងាត់ចាក់សោអេក្រង់។"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"តាមដាន​ការ​ព្យាយាម​ដោះ​សោ​អេក្រង់"</string>
@@ -1167,7 +1163,7 @@
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"សម្អាត​លំនាំដើម​ក្នុង​ការកំណត់​ប្រព័ន្ធ &gt; កម្មវិធី &gt; ទាញ​យក។"</string>
     <string name="chooseActivity" msgid="7486876147751803333">"ជ្រើស​សកម្មភាព​​"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"ជ្រើស​កម្មវិធី​សម្រាប់​ឧបករណ៍​យូអេសប៊ី"</string>
-    <string name="noApplications" msgid="2991814273936504689">"គ្មាន​កម្មវិធី​អាច​អនុវត្ត​សកម្មភាព​នេះ។"</string>
+    <string name="noApplications" msgid="2991814273936504689">"មិន​មាន​​កម្មវិធី​ដែលអាចធ្វើ​សកម្មភាពនេះ​បាន​ទេ។"</string>
     <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> បានឈប់"</string>
     <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> បានឈប់"</string>
     <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> ឈប់ដំណើរការម្តងហើយម្តងទៀត"</string>
@@ -1520,7 +1516,7 @@
     <string name="sync_do_nothing" msgid="3743764740430821845">"មិន​ធ្វើអ្វី​ទេ​ឥឡូវ"</string>
     <string name="choose_account_label" msgid="5655203089746423927">"ជ្រើស​គណនី"</string>
     <string name="add_account_label" msgid="2935267344849993553">"បញ្ចូល​គណនី​"</string>
-    <string name="add_account_button_label" msgid="3611982894853435874">"បន្ថែម​គណនី"</string>
+    <string name="add_account_button_label" msgid="3611982894853435874">"បញ្ចូល​គណនី"</string>
     <string name="number_picker_increment_button" msgid="2412072272832284313">"បង្កើន"</string>
     <string name="number_picker_decrement_button" msgid="476050778386779067">"បន្ថយ"</string>
     <string name="number_picker_increment_scroll_mode" msgid="5259126567490114216">"<xliff:g id="VALUE">%s</xliff:g> ប៉ះ និងសង្កត់ឲ្យជាប់"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 028d563..edcb6d1 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -324,8 +324,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ಪ್ರದರ್ಶನದ ಝೂಮ್ ಮಟ್ಟ ಮತ್ತು ಸ್ಥಾನ ನಿರ್ಧಾರವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ಗೆಸ್ಚರ್‌ಗಳನ್ನು ಮಾಡಿ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ಟ್ಯಾಪ್ ಮಾಡಬಹುದು, ಸ್ವೈಪ್ ಮಾಡಬಹುದು, ಪಿಂಚ್ ಮಾಡಬಹುದು ಮತ್ತು ಇತರ ಗೆಸ್ಚರ್‌ಗಳನ್ನು ಮಾಡಬಹುದು."</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್‌ ಸೂಚಕಗಳು"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ಸಾಧನದ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌ನಲ್ಲಿ ನಡೆಸಿದ ಸೂಚಕಗಳನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್‌ ಗೆಶ್ಚರ್‌ಗಳು"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ಸಾಧನದ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌ನಲ್ಲಿ ನಡೆಸಿದ ಗೆಶ್ಚರ್‌ಗಳನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇಲ್ಲವೇ ಮಾರ್ಪಡಿಸಿ"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಮತ್ತು ಸಿಸ್ಟಂ ಐಕಾನ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿರಲು"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ಮತ್ತು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದರರ್ಥ, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕಳುಹಿಸಲಾಗಿರುವ ಸಂದೇಶಗಳನ್ನು ನಿಮಗೆ ತೋರಿಸದೆಯೇ, ಅಪ್ಲಿಕೇಶನ್ ಅವುಗಳನ್ನು ಮಾನಿಟರ್ ಮಾಡಬಹುದು ಅಥವಾ ಅಳಿಸಬಹುದು."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ಪಠ್ಯ ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಿ (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ಮತ್ತು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದರರ್ಥ, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕಳುಹಿಸಲಾಗಿರುವ ಸಂದೇಶಗಳನ್ನು ನಿಮಗೆ ತೋರಿಸದೆಯೇ, ಅಪ್ಲಿಕೇಶನ್ ಅವುಗಳನ್ನು ಮಾನಿಟರ್ ಮಾಡಬಹುದು ಅಥವಾ ಅಳಿಸಬಹುದು."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"ಸೆಲ್ ಪ್ರಸಾರ ಸಂದೇಶಗಳನ್ನು ಫಾರ್ವರ್ಡ್ ಮಾಡಿ"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"ಸೆಲ್ ಪ್ರಸಾರವು ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಿದ ರೀತಿಯಲ್ಲಿಯೇ ಫಾರ್ವರ್ಡ್ ಮಾಡಲು, ಸೆಲ್ ಪ್ರಸಾರ ಮಾಡ್ಯುಲ್‌ ಅನ್ನು ಪ್ರತಿಬಂಧಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಕೆಲವು ಸ್ಥಳಗಳಲ್ಲಿ ತುರ್ತು ಸ್ಥಿತಿಗಳ ಕುರಿತು ನಿಮಗೆ ಎಚ್ಚರಿಸಲು ಸೆಲ್ ಪ್ರಸಾರದ ಎಚ್ಚರಿಕೆಗಳನ್ನು ಕಳುಹಿಸಲಾಗುತ್ತದೆ. ತುರ್ತು ಸೆಲ್‌ ಪ್ರಸಾರವನ್ನು ಸ್ವೀಕರಿಸಿದಾಗ ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಾಚರಣೆ ಅಥವಾ ಕಾರ್ಯಕ್ಷಮತೆಗೆ ದುರುದ್ದೇಶಪೂರಿತ ಆ್ಯಪ್‌ಗಳು ಹಸ್ತಕ್ಷೇಪ ಮಾಡಬಹುದು."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ಸೆಲ್ ಪ್ರಸಾರದ ಸಂದೇಶಗಳನ್ನು ಓದಿರಿ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ನಿಮ್ಮ ಸಾಧನದಿಂದ ಸ್ವೀಕರಿಸಿದ ಸೆಲ್ ಪ್ರಸಾರ ಸಂದೇಶಗಳನ್ನು ರೀಡ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸೆಲ್ ಪ್ರಸಾರ ಎಚ್ಚರಿಕೆಗಳನ್ನು ತುರ್ತು ಸಂದರ್ಭಗಳಲ್ಲಿ ನಿಮಗೆ ಎಚ್ಚರಿಸುವ ಸಲುವಾಗಿ ಕೆಲವು ಸ್ಥಳಗಳಲ್ಲಿ ವಿತರಿಸಲಾಗುತ್ತದೆ. ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್‌‌‌ಗಳು ತುರ್ತು ಸೆಲ್ ಪ್ರಸಾರವನ್ನು ಸ್ವೀಕರಿಸುವಾಗ, ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಕ್ಷಮತೆ ಇಲ್ಲವೇ ಕಾರ್ಯಾಚರಣೆಯಲ್ಲಿ ಹಸ್ತಕ್ಷೇಪ ಮಾಡಬಹುದು."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ಚಂದಾದಾರ ಫೀಡ್‌ಗಳನ್ನು ಓದಿ"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"ಆ್ಯಪ್‌ಗೆ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಸಂಕೀರ್ಣತೆ ಮಟ್ಟವನ್ನು (ಅಧಿಕ, ಮಧ್ಯಮ, ಕಡಿಮೆ ಅಥವಾ ಯಾವುದೂ ಅಲ್ಲ) ತಿಳಿದುಕೊಳ್ಳಲು ಅನುಮತಿಸುತ್ತದೆ, ಅದು ಉದ್ದದ ಸಂಭವನೀಯ ಶ್ರೇಣಿ ಮತ್ತು ಸ್ಕ್ರೀನ್ ಲಾಕ್‌ನ ವಿಧವನ್ನು ಸೂಚಿಸುತ್ತದೆ. ಬಳಕೆದಾರರು ನಿರ್ದಿಷ್ಟ ಹಂತದವರೆಗೆ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡಬಹುದು, ಆದರೆ ಅವರು ಅದನ್ನು ನಿರ್ಲಕ್ಷಿಸಬಹುದು ಮತ್ತು ಅದರಿಂದ ಹೊರಬರಬಹುದು ಎಂಬುದನ್ನು ಸಹ ಆ್ಯಪ್ ಬಳಕೆದಾರರಿಗೆ ಸೂಚಿಸುತ್ತದೆ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಪಠ್ಯದ ರೂಪದಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವುದಿಲ್ಲ, ಇದರಿಂದಾಗಿ ಆ್ಯಪ್‌ಗೆ ಸರಿಯಾದ ಪಾಸ್‌ವರ್ಡ್ ಗೊತ್ತಿರುವುದಿಲ್ಲ ಎಂಬುದನ್ನು ಗಮನಿಸಿ."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"ಬಯೋಮೆಟ್ರಿಕ್ ಹಾರ್ಡ್‌ವೇರ್‌ ಬಳಸಿ"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಬಯೋಮೆಟ್ರಿಕ್ ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ಬೆರಳಚ್ಚು ಹಾರ್ಡ್‌ವೇರ್ ನಿರ್ವಹಿಸಿ"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ಬಳಕೆಗೆ ಬೆರಳಚ್ಚು ಟೆಂಪ್ಲೇಟ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಮತ್ತು ಅಳಿಸಲು ವಿಧಾನಗಳನ್ನು ಮನವಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"ಬೆರಳಚ್ಚು ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಿ"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಬೆರಳಚ್ಚು ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಹಾರ್ಡ್‌ವೇರ್ ನಿರ್ವಹಿಸಿ"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ಬಳಕೆಗೆ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಟೆಂಪ್ಲೇಟ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಮತ್ತು ಅಳಿಸಲು ವಿಧಾನಗಳನ್ನು ಮನವಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಿ"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಲು ಆ್ಯಪ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"ನಿಮ್ಮ ಸಂಗೀತ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಿ"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"ನಿಮ್ಮ ಸಂಗೀತ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"ನಿಮ್ಮ ವೀಡಿಯೊ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಿ"</string>
@@ -534,9 +532,9 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"ಪ್ರಮಾಣೀಕರಣವನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"ಪಿನ್, ಪ್ಯಾಟರ್ನ್ ಅಥವಾ ಪಾಸ್‌ವರ್ಡ್ ಸೆಟ್ ಮಾಡಿಲ್ಲ"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ಭಾಗಶಃ ಬೆರಳಚ್ಚು ಪತ್ತೆಯಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ಬೆರಳಚ್ಚು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ಬೆರಳಚ್ಚು ಸೆನ್ಸರ್ ಮಲಿನಗೊಂಡಿದೆ. ದಯವಿಟ್ಟು ಅದನ್ನು ಸ್ವಚ್ಛಗೊಳಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ಭಾಗಶಃ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಪತ್ತೆಯಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಮಲಿನಗೊಂಡಿದೆ. ದಯವಿಟ್ಟು ಅದನ್ನು ಸ್ವಚ್ಛಗೊಳಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"ಬೆರಳನ್ನು ಅತಿ ವೇಗವಾಗಿ ಸರಿಸಲಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ಬೆರಳನ್ನು ತುಂಬಾ ನಿಧಾನವಾಗಿ ಸರಿಸಲಾಗಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -544,20 +542,20 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ಪ್ರಮಾಣೀಕರಣ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ, ದೃಢೀಕರಣವನ್ನು ಒತ್ತಿ"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ಬೆರಳಚ್ಚು ಹಾರ್ಡ್‌ವೇರ್‌ ಲಭ್ಯವಿಲ್ಲ."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ಬೆರಳಚ್ಚು ಸಂಗ್ರಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಬೆರಳಚ್ಚು ತೆಗೆದುಹಾಕಿ."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ಬೆರಳಚ್ಚು ಅವಧಿ ಮೀರಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ಬೆರಳಚ್ಚು ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆ."</string>
-    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ಬಳಕೆದಾರರಿಂದ ಫಿಂಗರ್‌ ಫ್ರಿಂಟ್‌ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಪಡಿಸಲಾಗಿದೆ."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಹಾರ್ಡ್‌ವೇರ್‌ ಲಭ್ಯವಿಲ್ಲ."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸಂಗ್ರಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ತೆಗೆದುಹಾಕಿ."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅವಧಿ ಮೀರಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆ."</string>
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ಬಳಕೆದಾರರು ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಪಡಿಸಿದ್ದಾರೆ."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ಹಲವಾರು ಪ್ರಯತ್ನಗಳು. ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ಹಲವು ಬಾರಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಫಿಂಗರ್‌ ಫ್ರಿಂಟ್‌ ಸೆನ್ಸಾರ್ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ಹಲವು ಬಾರಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"ಯಾವುದೇ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್‌ ಅನ್ನು ನೋಂದಣಿ ಮಾಡಿಲ್ಲ."</string>
     <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"ಈ ಸಾಧನವು ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌‌ ಅನ್ನು ಹೊಂದಿಲ್ಲ."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ಫಿಂಗರ್ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ಬೆರಳಚ್ಚು ಐಕಾನ್"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಐಕಾನ್"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"ಫೇಸ್ ಅನ್‌ಲಾಕ್ ಹಾರ್ಡ್‌ವೇರ್ ಅನ್ನು ನಿರ್ವಹಿಸಿ"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"ಬಳಕೆಗೆ ಮುಖದ ಟೆಂಪ್ಲೇಟ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಮತ್ತು ಅಳಿಸಲು ವಿಧಾನಗಳನ್ನು ಮನವಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"ಫೇಸ್ ಅನ್‌ಲಾಕ್ ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಿ"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ಓದಲು ಮತ್ತು ಬರೆಯಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"ವೀಕ್ಷಣಾ ಅನುಮತಿಯ ಬಳಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ಆ್ಯಪ್‌ಗಾಗಿ ಅನುಮತಿ ಬಳಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಲು ಹೊಂದಿರುವವರಿಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸಾಮಾನ್ಯ ಆ್ಯಪ್‌ಗಳಿಗೆ ಎಂದಿಗೂ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ಪ್ರವೇಶಿಸುವಿಕೆ ಶಾರ್ಟ್‌ಕಟ್ ಟಾರ್ಗೆಟ್‌"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ಪ್ರವೇಶಿಸುವಿಕೆ ಶಾರ್ಟ್‌ಕಟ್ ಟಾರ್ಗೆಟ್‌ ಅನ್ನು ವಿವರಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ಪಾಸ್‌ವರ್ಡ್ ನಿಮಯಗಳನ್ನು ಹೊಂದಿಸಿ"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"ಪರದೆ ಲಾಕ್‌ನಲ್ಲಿನ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಪಿನ್‌ಗಳ ಅನುಮತಿಸಲಾದ ಅಕ್ಷರಗಳ ಪ್ರಮಾಣವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"ಪರದೆಯ ಅನ್‌ಲಾಕ್ ಪ್ರಯತ್ನಗಳನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ"</string>
@@ -1589,7 +1585,7 @@
     <string name="serial_number" msgid="758814067660862493">"ಕ್ರಮ ಸಂಖ್ಯೆ:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"ಫಿಂಗರ್ ಪ್ರಿಂಟ್‌ಗಳು:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ಬೆರಳಚ್ಚು:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ಬೆರಳಚ್ಚು:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ಫಿಂಗರ್‌ಪ್ರಿಂಟ್:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"ಎಲ್ಲವನ್ನೂ ನೋಡಿ"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"ಚಟುವಟಿಕೆಯನ್ನು ಆರಿಸಿ"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"ಹಂಚಿಕೊಳ್ಳಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f81cc00..2f06bee 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"앱이 SMS 메시지를 수신하고 처리할 수 있도록 허용합니다. 앱이 사용자에게 표시하지 않고 기기로 전송된 메시지를 확인 또는 삭제할 수도 있습니다."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"문자 메시지 받기(MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"앱이 MMS 메시지를 수신하고 처리할 수 있도록 허용합니다. 앱이 사용자에게 표시하지 않고 기기로 전송된 메시지를 확인 또는 삭제할 수도 있습니다."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"셀 브로드캐스트 메시지 전달"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"셀 브로드캐스트 메시지를 수신하자마자 전달하기 위해 앱이 셀 브로드캐스트 모듈에 연결하도록 허용합니다. 비상 상황임을 알리기 위해 일부 지역에서 셀 브로드캐스트 경고가 전달됩니다. 비상 셀 브로드캐스트를 수신할 때 악성 앱이 기기의 성능이나 작동을 방해할 수 있습니다."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"셀 브로드캐스트 메시지 읽기"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"앱이 기기가 수신한 셀 브로드캐스트 메시지를 읽을 수 있도록 합니다. 비상 상황임을 알리기 위해 일부 지역에서 셀 브로드캐스트 경고가 전달됩니다. 비상 셀 브로드캐스트를 수신할 때 악성 앱이 기기의 성능이나 작동을 방해할 수 있습니다."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"가입된 피드 읽기"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"앱에서 방해 금지 모드 설정을 읽고 작성하도록 허용합니다."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"권한 사용 보기 시작"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"앱의 권한 사용을 시작하려면 보유자를 허용하세요. 일반 앱에는 필요하지 않습니다."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"접근성 단축키 대상"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"앱이 접근성 단축키 대상을 정의할 수 있도록 허용합니다."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 규칙 설정"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"화면 잠금 비밀번호와 PIN에 허용되는 길이와 문자 수를 제어합니다."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"화면 잠금 해제 시도 모니터링"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index c61992c..2353ed0 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Колдонмого SMS билдирүүлөрүн кабыл алууга жана аларды иштетип чыгууга уруксат берет. Бул, колдонмо сизге билгизбестен түзмөгүңүзгө жөнөтүлгөн билдирүүлөрдү мониторлой же жок кыла алат дегенди билдирет."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"билдирүүлөрдү (MMS) кабыл алуу"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Колдонмого MMS билдирүүлөрүн кабыл алууга жана аларды иштетип чыгууга уруксат берет. Бул, колдонмо сизге билгизбестен түзмөгүңүзгө жөнөтүлгөн билдирүүлөрдү мониторлой же жок кыла алат дегенди билдирет."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Уюк жөнөтүүлөрүнүн билдирүүлөрүн башка номерге багыттоо"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Уюк жөнөтүүлөрүнүн билдирүүлөрү келген сайын башка номерге багыттап туруу үчүн колдонмого уюк жөнөтүүлөрүнүн модулу менен байланышууга уруксат берет. Шашылыш уюк жөнөтүүлөрү кээ бир жерлердеги өзгөчө кырдаалдар тууралуу сизге эскертүү үчүн жөнөтүлөт. Зыянкеч колдонмолор шашылыш уюк жөнөтүүлөрү кабыл алынганда түзмөктүн майнаптуулугуна же иштешине жолтоо болушу мүмкүн."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"уюктук берүү билдирүүлөрүн окуу"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Колдонмого түзмөгүңүз кабыл алган уюк берүүнүн билдирүүлөрүн окууга жол берет. Шашылыш эскертүү билдирүүлөрү кээ бир жерлердеги өзгөчө кырдаалдар тууралу сизди эскертүү үчүн жөнөтүлөт. Зыяндуу колдономолор шашылыш эскертүүлөр берилип жатканда, сиздин түзмөктүн иштешине жолтоо болушу мүмкүн."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"жазылган түрмөктөрдү окуу"</string>
@@ -541,14 +539,14 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Манжа өтө жай жылды. Кайра аракет кылыңыз."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Манжа изинин аныктыгы текшерилди"</string>
+    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Манжа изи текшерилди"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Жүздүн аныктыгы текшерилди"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Жүздүн аныктыгы текшерилди, эми \"Ырастоону\" басыңыз"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Манжа изинин аппараттык камсыздоосу жеткиликтүү эмес."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Манжа изин сактоо мүмкүн эмес. Учурдагы манжа изин алып салыңыз."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Манжа изин күтүү мөөнөтү бүттү. Кайра аракет кылыңыз."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Манжа изи иш-аракети жокко чыгарылды."</string>
-    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Манжа изи менен аныктыгын текшерүүнү колдонуучу жокко чыгарды."</string>
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Манжа изи операциясын колдонуучу жокко чыгарды."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Аракеттер өтө көп болду. Кийинчерээк кайра аракет кылыңыз."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Өтө көп жолу аракет жасадыңыз. Манжа изинин сенсору өчүрүлдү."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Кайра бир аракеттениңиз."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Колдонмого \"Тынчымды алба\" режиминин конфигурациясын окуу жана жазуу мүмкүнчүлүгүн берет."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"уруксаттын колдонулушун көрүп баштоо"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Колдонмонун пайдаланылышына уруксат берүүгө мүмкүнчүлүк берет. Кадимки колдонмолорго эч качан талап кылынбашы керек."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"максаттуу атайын мүмкүнчүлүк аракетине кыска жол"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Колдонмого максаттуу атайын мүмкүнчүлүк аракетине кыска жолду аныктоого уруксат берет."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Сырсөз эрежелерин коюу"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Экран кулпусунун сырсөздөрү менен PIN\'дерине уруксат берилген узундук менен белгилерди көзөмөлдөө."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Экран кулпусун ачуу аракеттерин көзөмөлдөө"</string>
@@ -1591,7 +1587,7 @@
     <string name="fingerprints" msgid="4516019619850763049">"Манжа издери:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 манжа изи:"</string>
     <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 манжа изи:"</string>
-    <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Бардыгын көрүү"</string>
+    <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Баарын көрүү"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Аракетти тандаңыз"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Төмөнкү менен бөлүшүү"</string>
     <string name="sending" msgid="3245653681008218030">"Жөнөтүлүүдө…"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index fb3afb3..a83fae1 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"ອະນຸຍາດໃຫ້ແອັບຯຮັບ ແລະປະມວນຜົນຂໍ້ຄວາມ SMS. ນີ້ໝາຍຄວາມວ່າແອັບຯສາມາດຕິດຕາມ ຫຼືລຶບຂໍ້ຄວາມທີ່ສົ່ງເຂົ້າອຸປະກອນຂອງທ່ານ ໂດຍທີ່ບໍ່ສະແດງພວກມັນໃຫ້ທ່ານເຫັນ."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ຮັບຂໍ້ຄວາມ (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"ອະນຸຍາດໃຫ້ແອັບຯ ຮັບແລະປະມວນຜົນຂໍ້ຄວາມ MMS. ນີ້ໝາຍຄວາມວ່າແອັບຯສາມາດຕິດຕາມ ຫຼືລຶບຂໍ້ຄວາມທີ່ສົ່ງເຂົ້າອຸປະກອນຂອງທ່ານ ໂດຍທີ່ບໍ່ສະແດງພວກມັນໃຫ້ທ່ານເຫັນ."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"ສົ່ງຕໍ່ຂໍ້ຄວາມການກະຈາຍສັນຍານໂທລະສັບ"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"ອະນຸຍາດໃຫ້ແອັບຜູກມັດກັບໂມດູນການກະຈາຍສັນຍານໂທລະສັບເພື່ອສົ່ງຕໍ່ຂໍ້ຄວາມການກະຈາຍສັນຍານໂທລະສັບເມື່ອໄດ້ຮັບມາ. ການເຕືອນການກະຈາຍສັນຍານໂທລະສັບແມ່ນຖືກຈັດສົ່ງໃນບາງສະຖານທີ່ເພື່ອເຕືອນທ່ານໃນກໍລະນີມີເຫດການສຸກເສີນເກີດຂຶ້ນ. ແອັບທີ່ເປັນອັນຕະລາຍອາດລົບກວນປະສິດທິພາບ ຫຼື ການເຮັດວຽກຂອງອຸປະກອນທ່ານເມື່ອໄດ້ຮັບການກະຈາຍສັນຍານໂທລະສັບສຸກເສີນ."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ອ່ານຂໍ້ຄວາມກະຈາຍສັນຍານຂອງເສົາສັນຍານ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ອະນຸຍາດໃຫ້ແອັບຯ ສາມາດອ່ານຂໍ້ຄວາມແຈ້ງເຕືອນເຫດສຸກເສີນ ທີ່ໄດ້ຮັບໂດຍອຸປະກອນຂອງທ່ານ. ການແຈ້ງເຕືອນສຸກເສີນທີ່ມີໃຫ້ບໍລິການໃນບາງພື້ນທີ່ ເພື່ອແຈ້ງເຕືອນໃຫ້ທ່ານຮູ້ເຖິງສະຖານະການສຸກເສີນ. ແອັບພລິເຄຊັນທີ່ເປັນອັນຕະລາຍອາດລົບກວນປະສິດທິພາບ ຫຼືການດຳເນີນງານຂອງອຸປະກອນຂອງທ່ານ ເມື່ອໄດ້ການຮັບແຈ້ງເຕືອນສຸກເສີນຈາກສະຖານີມືຖື."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ອ່ານຂໍ້ມູນຟີດທີ່ສະໝັກໄວ້"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"ອະນຸຍາດ​​ໃຫ້​ແອັບ​ອ່ານ​ ​ແລະ​ຂຽນການກນຳ​ດຄ່າ ບໍ່​ລົບ​ກວນ."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"ເລີ່ມການໃຊ້ສິດອະນຸຍາດການເບິ່ງ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ອະນຸຍາດໃຫ້ຜູ້ຖືເລີ່ມການໃຊ້ສິດອະນຸຍາດສຳລັບແອັບໃດໜຶ່ງໄດ້. ແອັບປົກກະຕິບໍ່ຄວນຕ້ອງໃຊ້."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ເປົ້າໝາຍທາງລັດການຊ່ວຍເຂົ້າເຖິງ"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ອະນຸຍາດໃຫ້ແອັບລະບຸເປົ້າໝາຍທາງລັດການຊ່ວຍເຂົ້າເຖິງ."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ຕັ້ງຄ່າກົດຂອງລະຫັດຜ່ານ"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"ຄວບຄຸມຄວາມຍາວ ແລະຕົວອັກສອນທີ່ອະ​ນຸ​ຍາດ​ໃຫ້​ຢູ່​ໃນລະ​ຫັດລັອກໜ້າຈໍ ແລະ PIN."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"ຕິດຕາມການພະຍາຍາມປົດລັອກໜ້າຈໍ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index be9e32f..fdd5d2a 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Leidžiama programai gauti ir apdoroti SMS pranešimus. Tai reiškia, kad programa gali stebėti ir ištrinti į jūsų įrenginį siunčiamus pranešimus jums jų neparodžiusi."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"gauti teksto pranešimus (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Leidžiama programai gauti ir apdoroti MMS pranešimus. Tai reiškia, kad programa gali stebėti ir ištrinti į jūsų įrenginį siunčiamus pranešimus jums jų neparodžiusi."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Persiųsti mobiliuoju transliuojamus pranešimus"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Programai leidžiama susaistyti transliacijos mobiliuoju modulį, kad būtų galima persiųsti mobiliuoju transliuojamus pranešimus, kai jie gaunami. Transliacijos mobiliuoju įspėjimai pristatomi kai kuriose vietovėse, kad būtų galima įspėti apie kritines situacijas. Kai gaunamas mobiliuoju transliuojamas pranešimas apie kritinę situaciją, kenkėjiškos programos gali trukdyti įrenginiui veikti ar jį naudoti."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"skaityti mobiliuoju transliuojamus pranešimus"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Programai leidžiama skaityti mobiliuoju transliuojamus pranešimus, gaunamus jūsų įrenginyje. Mobiliuoju transliuojami įspėjimai pristatomi kai kuriose vietose, kad įspėtų apie kritines situacijas. Kai gaunamas  mobiliuoju transliuojamas pranešimas apie kritinę situaciją, kenkėjiškos programos gali trukdyti įrenginiui veikti ar jį naudoti."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"skaityti prenumeruojamus tiekimus"</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Leidžiama programai skaityti ir rašyti „Do Not Disturb“ konfigūraciją."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"pradėti peržiūrėti leidimo naudojimą"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Leidžia savininkui pradėti naudoti programos leidimą. Įprastoms programoms to neturėtų prireikti."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"pritaikomumo sparčiojo klavišo tikslas"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Programai leidžiama apibrėžti pritaikomumo sparčiojo klavišo tikslą."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nustatyti slaptažodžio taisykles"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Valdykite, kokio ilgio ekrano užrakto slaptažodžius ir PIN kodus galima naudoti."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Stebėti bandymus atrakinti ekraną"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 89575c6..d1b7764 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -347,10 +347,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Ļauj lietotnei saņemt un apstrādāt īsziņas. Tas nozīmē, ka lietotne var pārraudzīt vai dzēst uz jūsu ierīci nosūtītos ziņojumus, neparādot tos jums."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"saņemt ziņojumus (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Ļauj lietotnei saņemt un apstrādāt multiziņas. Tas nozīmē, ka lietotne var pārraudzīt vai dzēst uz jūsu ierīci nosūtītos ziņojumus, neparādot tos jums."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Pārsūtīt šūnu apraides ziņojumus"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Ļauj piesaistīt lietotni šūnu apraides modulim, lai pārsūtītu šūnu apraides ziņojumus, tiklīdz tie tiek saņemti. Šūnu apraides brīdinājumi tiek piegādāti noteiktās atrašanās vietās, lai brīdinātu jūs par ārkārtas situācijām. Ļaunprātīgas lietotnes var traucēt ierīces veiktspēju vai darbības, kad ir saņemts ārkārtas šūnas apraides ziņojums."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"šūnu apraides ziņojumu lasīšana"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Ļauj lietotnei lasīt ierīcē saņemtos šūnu apraides ziņojumus. Šūnu apraides brīdinājumi tiek piegādāti dažās atrašanās vietās, lai brīdinātu jūs par ārkārtas situācijām. Ļaunprātīgas lietotnes var traucēt ierīces veiktspēju vai darbības, kad ir saņemts ārkārtas šūnas apraides ziņojums."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lasīt abonētās plūsmas"</string>
@@ -662,8 +660,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Ļauj lietotnei lasīt un rakstīt režīma “Netraucēt” konfigurāciju."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"Datu skatīšana par izmantojamajām atļaujām"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Ļauj atļaujas īpašniekam sākt lietotnes atļauju izmantošanu. Parastām lietotnēm tas nekad nav nepieciešams."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"pieejamības īsinājumtaustiņa mērķis"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Ļauj lietotnei definēt pieejamības īsinājumtaustiņa mērķi."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Paroles kārtulu iestatīšana"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolēt ekrāna bloķēšanas paroļu un PIN garumu un tajos atļautās rakstzīmes."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string>
diff --git a/core/res/res/values-mcc310-mnc030-da/strings.xml b/core/res/res/values-mcc310-mnc030-da/strings.xml
index c45e3be..3dbda05 100644
--- a/core/res/res/values-mcc310-mnc030-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc030-da/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="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="2995576894416087107">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc170-da/strings.xml b/core/res/res/values-mcc310-mnc170-da/strings.xml
index 8580fb3..6a4d3e8 100644
--- a/core/res/res/values-mcc310-mnc170-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc170-da/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="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="3173546391131606065">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc280-da/strings.xml b/core/res/res/values-mcc310-mnc280-da/strings.xml
index 6a8e40b..919ac32 100644
--- a/core/res/res/values-mcc310-mnc280-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc280-da/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="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="822496463303720579">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc380-da/strings.xml b/core/res/res/values-mcc310-mnc380-da/strings.xml
index cd4c796..8b8ac1a 100644
--- a/core/res/res/values-mcc310-mnc380-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc380-da/strings.xml
@@ -20,6 +20,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM-kort er ikke tilladt MM#3"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc410-da/strings.xml b/core/res/res/values-mcc310-mnc410-da/strings.xml
index 3c5b9ee..3c9ab9c 100644
--- a/core/res/res/values-mcc310-mnc410-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc410-da/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="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="4477688981805467729">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc560-da/strings.xml b/core/res/res/values-mcc310-mnc560-da/strings.xml
index 95c214b..aac050c 100644
--- a/core/res/res/values-mcc310-mnc560-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc560-da/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="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="7030488670186895244">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc950-da/strings.xml b/core/res/res/values-mcc310-mnc950-da/strings.xml
index 97c801b..e8ab75c 100644
--- a/core/res/res/values-mcc310-mnc950-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc950-da/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="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="8920048244573695129">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc311-mnc180-da/strings.xml b/core/res/res/values-mcc311-mnc180-da/strings.xml
index 5bcc43d..624a1c03 100644
--- a/core/res/res/values-mcc311-mnc180-da/strings.xml
+++ b/core/res/res/values-mcc311-mnc180-da/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="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="5766888847785331904">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 7144e4d..d30c8f2 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Овозможува апликацијата да прима и да обработува SMS пораки. Тоа значи дека апликацијата може да следи или да брише пораки испратени до вашиот уред без да ви ги прикаже вам."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"прими текстуални пораки (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Овозможува апликацијата да прима и да обработува MMS пораки. Тоа значи дека апликацијата може да следи или да брише пораки испратени до вашиот уред без да ви ги прикаже вам."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Проследување пораки за мобилен пренос"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Дозволува апликацијата да се врзе со модулот за мобилен пренос за да проследува пораки за мобилен пренос штом ќе се примат. Предупредувањата за мобилно емитување се доставуваат на некои локации за да ве предупредат на итни ситуации. Злонамерните апликации може да пречат во ефикасноста или работењето на вашиот уред кога се прима емитување за итен случај."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"прочитај пораки за мобилно емитување"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Овозможува апликациите да ги читаат пораките за мобилно емитување што ги прима вашиот уред. Предупредувањата за мобилно емитување се доставуваат на некои локации, за да ве предупредат на итни ситуации. Злонамерните апликации може да пречат во ефикасноста или работењето на вашиот уред кога се прима емитување за итен случај."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"читај претплатени навестувања на содржина"</string>
@@ -544,10 +542,10 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Отпечатокот е проверен"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Лицето е проверено"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Лицето е проверено, притиснете го копчето „Потврди“"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хардвер за отпечаток од прст не е достапен."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Отпечатокот не може да се складира. Отстранете го постоечкиот отпечаток."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хардверот за отпечатоци не е достапен."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Отпечатокот не може да се складира. Отстранете некој од постојните отпечатоци."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Се достигна времето на истекување на отпечатокот. Обидете се повторно."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Операцијата со отпечаток од прст се откажа."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Операцијата со отпечаток се откажа."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Корисникот ја откажа потврдата со отпечаток."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Премногу обиди. Обидете се повторно подоцна."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Премногу обиди. Сензорот за отпечатоци е оневозможен."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Дозволува апликацијата да чита и пишува конфигурација Не вознемирувај."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"започнете со користење на дозволата за приказ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Дозволува сопственикот да почне со користење на дозволата за апликација. Не треба да се користи за стандардни апликации."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"цел на кратенката за пристапност"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Дозволува апликација да одреди цел на кратенката за пристапност."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Постави правила за лозинката"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Контролирај ги должината и знаците што се дозволени за лозинки и PIN-броеви за отклучување екран."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Следи ги обидите за отклучување на екранот"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 479bb3a..5a604fb 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -325,7 +325,7 @@
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ജെസ്‌റ്ററുകൾ നിർവഹിക്കുക"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ടാപ്പുചെയ്യാനോ സ്വൈപ്പുചെയ്യാനോ പിഞ്ചുചെയ്യാനോ മറ്റ് ജെസ്‌റ്ററുകൾ നിർവഹിക്കാനോ കഴിയും."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ഫിംഗർപ്രിന്റ് ജെസ്‌റ്ററുകൾ"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ഉപകരണത്തിന്റെ വിരലടയാള സെൻസറിൽ ചെയ്‌ത ജെസ്‌റ്ററുകൾ ക്യാപ്‌ചർ ചെയ്യാനാകും."</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ഉപകരണത്തിന്റെ ഫിംഗർപ്രിന്റ് സെൻസറിൽ ചെയ്‌ത ജെസ്‌റ്ററുകൾ ക്യാപ്‌ചർ ചെയ്യാനാകും."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"സ്റ്റാറ്റസ് ബാർ പ്രവർത്തനരഹിതമാക്കുക അല്ലെങ്കിൽ പരിഷ്‌ക്കരിക്കുക"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"നില ബാർ പ്രവർത്തരഹിതമാക്കുന്നതിന് അല്ലെങ്കിൽ സിസ്‌റ്റം ഐക്കണുകൾ ചേർക്കുന്നതിനും നീക്കംചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"സ്റ്റാറ്റസ് ബാർ ആയിരിക്കുക"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS സന്ദേശങ്ങൾ നേടാനും പ്രോസസ്സുചെയ്യാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് അയയ്‌ക്കുന്ന സന്ദേശങ്ങൾ നിങ്ങൾക്ക് ദൃശ്യമാക്കാതെ തന്നെ അപ്ലിക്കേഷന് നിരീക്ഷിക്കാനോ ഇല്ലാതാക്കാനോ കഴിയുമെന്നാണ് ഇതിനർത്ഥം."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"വാചക സന്ദേശം നേടുക (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS സന്ദേശങ്ങൾ നേടാനും പ്രോസസ്സുചെയ്യാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് അയയ്‌ക്കുന്ന സന്ദേശങ്ങൾ നിങ്ങൾക്ക് ദൃശ്യമാക്കാതെ തന്നെ അപ്ലിക്കേഷന് നിരീക്ഷിക്കാനോ ഇല്ലാതാക്കാനോ കഴിയുമെന്നാണ് ഇതിനർത്ഥം."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"ബ്രോഡ്‌കാസ്‌റ്റ് സന്ദേശങ്ങൾ കൈമാറുക"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"സ്വീകരിക്കുന്ന മുറയ്ക്ക് ബ്രോഡ്‌കാസ്‌റ്റ് സന്ദേശങ്ങൾ കൈമാറുന്നതിന് സെൽ ബ്രോഡ്‌കാസ്‌റ്റ് മോഡ്യൂളിലേക്ക് ബൈൻഡ് ചെയ്യാൻ ആപ്പിനെ അനുവദിക്കുന്നു. അടിയന്തര സാഹചര്യങ്ങളെ കുറിച്ച് നിങ്ങൾക്ക് മുന്നറിയിപ്പ് നൽകുന്നതിന് ചില ലൊക്കേഷനുകളിൽ സെൽ ബ്രോഡ്‌കാസ്‌റ്റ് അലേർട്ടുകൾ ഡെലിവറി ചെയ്യപ്പെടുന്നു. ഒരു അടിയന്തര സെൽ ബ്രോഡ്‌കാസ്റ്റ് ലഭിക്കുമ്പോൾ ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനത്തെയോ പ്രവർത്തനത്തെയോ തടസപ്പെടുത്താനിടയുണ്ട്."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"സെൽ പ്രക്ഷേപണ സന്ദേശങ്ങൾ റീഡുചെയ്യുക"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"നിങ്ങളുടെ ഉപകരണത്തിൽ ലഭിച്ച സെൽ പ്രക്ഷേപണ സന്ദേശങ്ങൾ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. അടിയന്തര സാഹചര്യങ്ങളെക്കുറിച്ച് നിങ്ങൾക്ക് മുന്നറിയിപ്പ് നൽകാനായി ചില ലൊക്കേഷനുകളിൽ നൽകപ്പെടുന്നവയാണ് സെൽ പ്രക്ഷേപണ അലേർട്ടുകൾ. ഒരു അടിയന്തര സെൽ പ്രക്ഷേപണം ലഭിക്കുമ്പോൾ, ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനമോ പ്രവർത്തനമോ തടസ്സപ്പെടുത്താനിടയുണ്ട്."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"സബ്‌സ്ക്രൈബ് ചെയ്‌ത ഫീഡുകൾ വായിക്കുക"</string>
@@ -517,9 +515,9 @@
     <string name="permlab_useBiometric" msgid="8837753668509919318">"ബയോമെട്രിക് ഹാർ‌ഡ്‌വെയർ ഉപയോഗിക്കുക"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"പരിശോധിച്ചുറപ്പിക്കുന്നതിനായി, ബയോമെട്രിക് ഹാർഡ്‌വെയർ ഉപയോഗിക്കാൻ ആപ്പിനെ അനുവദിക്കുക"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ഫിംഗർപ്രിന്റ് ഹാർഡ്‌വെയർ നിയന്ത്രിക്കുക"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ഉപയോഗിക്കാനായി വിരലടയാള ടെംപ്ലേറ്റുകൾ ചേർക്കാനും ഇല്ലാതാക്കാനുമുള്ള രീതികൾ അഭ്യർത്ഥിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ഉപയോഗിക്കാനായി ഫിംഗർപ്രിന്റ് ടെംപ്ലേറ്റുകൾ ചേർക്കാനും ഇല്ലാതാക്കാനുമുള്ള രീതികൾ അഭ്യർത്ഥിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ഫിംഗർപ്രിന്റ് ഹാർഡ്‌വെയർ ഉപയോഗിക്കുക"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"പ്രാമാണീകരണത്തിനായി വിരലടയാളം ഉപയോഗിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"പ്രാമാണീകരണത്തിനായി ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"നിങ്ങളുടെ സംഗീത ശേഖരം പരിഷ്‌കരിക്കുക"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"നിങ്ങളുടെ സംഗീത ശേഖരം പരിഷ്‌ക്കരിക്കുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"നിങ്ങളുടെ വീഡിയോ ശേഖരം പരിഷ്‌കരിക്കുക"</string>
@@ -534,9 +532,9 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"തിരിച്ചറിഞ്ഞില്ല"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"പരിശോധിച്ചുറപ്പിക്കൽ റദ്ദാക്കി"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"പിന്നോ പാറ്റേണോ പാസ്‌വേഡോ സജ്ജീകരിച്ചിട്ടില്ല"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"വിരലടയാളം ഭാഗികമായി തിരിച്ചറിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"വിരലടയാളം പ്രോസസ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"വിരലടയാള സെൻസറിൽ ചെളിയുണ്ട്. അത് വൃത്തിയാക്കി വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ഫിംഗർപ്രിന്റ് ഭാഗികമായി തിരിച്ചറിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ഫിംഗർപ്രിന്റ് പ്രോസസ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ഫിംഗർപ്രിന്റ് സെൻസറിൽ ചെളിയുണ്ട്. അത് വൃത്തിയാക്കി വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"വിരൽ വളരെ വേഗത്തിൽ നീക്കി. വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"വിരൽ വളരെ പതുക്കെ നീക്കി. വീണ്ടും ശ്രമിക്കുക."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -545,19 +543,19 @@
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു, സ്ഥിരീകരിക്കുക അമർത്തുക"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ഫിംഗർപ്രിന്റ് ഹാർഡ്‌വെയർ ലഭ്യമല്ല."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"വിരലടയാളം സംഭരിക്കാനാവില്ല. നിലവിലുള്ള വിരലടയാളം നീക്കംചെയ്യുക."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"വിരലടയാളം നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ഫിംഗർപ്രിന്റ് സംഭരിക്കാനാവില്ല. നിലവിലുള്ള ഫിംഗർപ്രിന്റ് നീക്കംചെയ്യുക."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ഫിംഗർപ്രിന്റ് നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ഫിംഗർപ്രിന്റ് പ്രവർത്തനം റദ്ദാക്കി."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ഉപയോക്താവ് റദ്ദാക്കിയ ഫിംഗർപ്രിന്‍റ് പ്രവർത്തനം."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"നിരവധി തവണ ശ്രമിച്ചു. പിന്നീട് വീണ്ടും ശ്രമിക്കുക."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"നിരവധി തവണ ശ്രമിച്ചതിനാൽ, വിരലടയാള സെൻസർ പ്രവർത്തനരഹിതമായി."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"നിരവധി തവണ ശ്രമിച്ചതിനാൽ, ഫിംഗർപ്രിന്റ് സെൻസർ പ്രവർത്തനരഹിതമായി."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"വീണ്ടും ശ്രമിക്കൂ."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"വിരലടയാളങ്ങൾ എൻറോൾ ചെയ്തിട്ടില്ല."</string>
-    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"ഈ ഉപകരണത്തിൽ വിരലടയാള സെൻസറില്ല."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"ഈ ഉപകരണത്തിൽ ഫിംഗർപ്രിന്റ് സെൻസറില്ല."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"കൈവിരൽ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"വിരലടയാള ഐക്കൺ"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ഫിംഗർപ്രിന്റ് ഐക്കൺ"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് ഹാർഡ്‌വെയർ മാനേജ് ചെയ്യുക"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"ഉപയോഗിക്കാനായി, മുഖത്തിന്റെ ടെംപ്ലേറ്റുകൾ ചേർക്കാനും ഇല്ലാതാക്കാനുമുള്ള രീതികൾ അഭ്യർത്ഥിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് ഹാർഡ്‌വെയർ ഉപയോഗിക്കുക"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"\'ശല്യപ്പെടുത്തരുത്\' കോൺഫിഗറേഷൻ വായിക്കുന്നതിനും എഴുതുന്നതിനും ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"അനുമതി ഉപയോഗം കാണാൻ ആരംഭിക്കുക"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ഒരു ആപ്പിനുള്ള അനുമതി ഉപയോഗം ആരംഭിക്കാൻ ഹോൾഡറിനെ അനുവദിക്കുന്നു. സാധാരണ ആപ്പുകൾക്ക് ഒരിക്കലും ആവശ്യമില്ല."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ഉപയോഗസഹായി കുറുക്കുവഴിയുടെ ടാർഗറ്റ്"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ഉപയോഗസഹായി കുറുക്കുവഴിയുടെ ടാർഗറ്റ് നിർവ്വചിക്കാൻ ആപ്പിനെ അനുവദിക്കുക."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"പാസ്‌വേഡ് നിയമങ്ങൾ സജ്ജീകരിക്കുക"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"സ്‌ക്രീൻ ലോക്ക് പാസ്‌വേഡുകളിലും PIN-കളിലും അനുവദിച്ചിരിക്കുന്ന ദൈർഘ്യവും പ്രതീകങ്ങളും നിയന്ത്രിക്കുക."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"സ്‌ക്രീൻ അൺലോക്ക് ശ്രമങ്ങൾ നിരീക്ഷിക്കുക"</string>
@@ -1589,7 +1585,7 @@
     <string name="serial_number" msgid="758814067660862493">"സീരിയൽ നമ്പർ:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"വിരലടയാളങ്ങൾ:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 വിരലടയാളം:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA വിരലടയാളം:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA ഫിംഗർപ്രിന്റ്:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"എല്ലാം കാണുക"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"പ്രവർത്തനം തിരഞ്ഞെടുക്കുക"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"ഇവരുമായി പങ്കിടുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 1f29956..f4c6b60 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Апп нь SMS мессежийг хүлээн авах болон гүйцэтгэх боломжтой. Ингэснээр апп нь таны төхөөрөмжрүү илгээсэн мессежийг танд үзүүлэхгүйгээр хянах болон устгаж чадна."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"текст мессеж(МMS) хүлээж авах"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Апп нь MMS мессежийг хүлээн авах болон гүйцэтгэх боломжтой. Ингэснээр апп нь таны төхөөрөмжрүү илгээсэн мессежийг танд үзүүлэхгүйгээр хянах болон устгаж чадна."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Гар утсанд масс мессеж түгээх онцлогийн мессежийг шилжүүлэх"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Гар утсанд масс мессеж түгээх онцлогийн мессежийг хүлээн авах үед түүнийг шилжүүлэх зорилгоор аппад гар утсанд масс мессеж түгээх модультай холбогдохыг зөвшөөрөх Гар утсанд масс мессеж түгээх онцлогийн сэрэмжлүүлэг нь онцгой нөхцөл байдлын тухай танд анхааруулахын тулд зарим байршилд хүрдэг. Гар утсанд масс мессеж түгээх онцлогийн илгээх онцгой нөхцөл байдлын тухай мессежийг хүлээн авах үед хортой апп таны төхөөрөмжийн гүйцэтгэл эсвэл ажиллагаанд саад учруулж болзошгүй."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"үүрэн өргөн дамжууллын мессеж унших"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Апп нь таны төхөөрөмжийн хүлээн авсан үүрэн өргөн дамжуулах мессежийг унших боломжтой. Үүрэн өргөн дамжууллын мэдэгдэл нь яаралтай нөхцөл байдлыг анхааруулах зорилгоор зарим байршлуудад хүрдэг. Хортой апп нь яаралтай үүрэн өргөн дамжууллыг хүлээн авсан үед таны төхөөрөмжийн ажиллагаа болон чадамжид нөлөөлөх боломжтой."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"бүртгүүлсэн хангамжийг унших"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Аппад дэлгэцийн түгжээний боломжтой уртын хэмжээ болон төрлийг заадаг дэлгэцийн түгжээний төвөгтэй байдлын түвшнийг (өндөр, дундаж, бага эсвэл байхгүй) мэдэж авахыг зөвшөөрдөг. Түүнчлэн, апп хэрэглэгчдэд дэлгэцийн түгжээг тодорхой түвшинд шинэчлэхийг санал болгох боломжтой хэдий ч хэрэглэгч үүнийг чөлөөтэй үл хэрэгсэж, орхих боломжтой. Дэлгэцийн түгжээг ил бичвэрээр хадгалдаггүй тул энэ апп тодорхой нууц үгийг мэддэггүй болохыг анхаарна уу."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"биометрийн техник хангамжийг ашиглах"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Aппад биометрийн техник хангамжийг баталгаажуулалтад ашиглахыг зөвшөөрдөг"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"хурууны хээний програм хангамжийг удирдах"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Хурууны хээний загварыг нэмэх эсвэл усгтах үйлдлийг хийх зөвшөөрлийг програмд олгодог."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"хурууны хээний програм хангамжийг ашиглах"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Баталгаажуулалт хийх зорилгоор хурууны хээний апп хамгамжийг ашиглах зөвшөөрлийг аппд олгодог"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"хурууны хээний төхөөрөмжийг удирдах"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Хурууны хээний загвар нэмэх эсвэл устгах үйлдэл хийх зөвшөөрлийг аппд олгодог."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"хурууны хээний төхөөрөмж ашиглах"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Баталгаажуулалт хийх зорилгоор хурууны хээний төхөөрөмжийг ашиглах зөвшөөрлийг аппд олгодог"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"хөгжмийн цуглуулгаа тохируулах"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Таны хөгжмийн цуглуулгыг тохируулах зөвшөөрлийг аппад олгодог."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"видео цуглуулгаа тохируулах"</string>
@@ -536,7 +534,7 @@
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Тохируулсан пин, хээ эсвэл нууц үг алга"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Хурууны хээг дутуу уншуулсан байна. Дахин оролдоно уу."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Хурууны хээ боловсруулж чадахгүй байна. Дахин оролдоно уу."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Хурууны хээ мэдрэгч бохирдсон байна. Та цэвэрлэсний дараагаар дахин оролдоно уу."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Хурууны хээ мэдрэгч бохирдсон байна. Цэвэрлэсний дараа дахин оролдоно уу."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Хуруугаа хэт хурдан хөдөлгөсөн байна. Дахин оролдоно уу."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Хуруу хэт удаан хөдөлгөсөн байна. Дахин оролдоно уу."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -544,11 +542,11 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Хурууны хээг нотолсон"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Царайг баталгаажууллаа"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Царайг баталгаажууллаа. Баталгаажуулах товчлуурыг дарна уу"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хурууны хээний тоног төхөөрөмж бэлэн бус байна."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хурууны хээний төхөөрөмж бэлэн бус байна."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Хурууны хээг хадгалах боломжгүй байна. Одоо байгаа хурууны хээг арилгана уу."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Хурууны хээ оруулах хугацаа өнгөрсөн байна. Дахин оруулна уу."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Хурууны хээний бүртгэл амжилтгүй боллоо."</string>
-    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Хэрэглэгч хурууны хээн баталгаажуулалтыг цуцалсан байна."</string>
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Хэрэглэгч хурууны хээний баталгаажуулалтыг цуцалсан байна."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Хэтэрхий олон оролдлоо.  Түр хүлээгээд дахин оролдоно уу."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Хэт олон удаа оролдсон тул хурууны хээ мэдрэгчийг идэвхгүй болголоо."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Дахин оролдно уу."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Апп-д Бүү саад бол тохируулгыг уншиж, бичихийг зөвшөөрөх"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"зөвшөөрлийн ашиглалтыг харж эхлэх"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Эзэмшигчид аппын зөвшөөрлөө ашиглаж эхлэхийг зөвшөөрдөг. Энгийн аппуудад шаардлагагүй."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"хандалтын товчлолын зорилт"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Аппад хандалтын товчлолын зорилтыг тодорхойлохыг зөвшөөрдөг."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Нууц үгний дүрмийг тохируулах"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Дэлгэц түгжих нууц үг болон ПИН кодны урт болон нийт тэмдэгтийн уртыг хянах."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Дэлгэцийн түгжээг тайлах оролдлогыг хянах"</string>
@@ -1518,7 +1514,7 @@
     <string name="sync_do_nothing" msgid="3743764740430821845">"Одоо юу ч хийхгүй"</string>
     <string name="choose_account_label" msgid="5655203089746423927">"Бүртгэл сонгох"</string>
     <string name="add_account_label" msgid="2935267344849993553">"Бүртгэл нэмэх"</string>
-    <string name="add_account_button_label" msgid="3611982894853435874">"Аккаунт нэмэх"</string>
+    <string name="add_account_button_label" msgid="3611982894853435874">"Бүртгэл нэмэх"</string>
     <string name="number_picker_increment_button" msgid="2412072272832284313">"Өсөх"</string>
     <string name="number_picker_decrement_button" msgid="476050778386779067">"Бууруулах"</string>
     <string name="number_picker_increment_scroll_mode" msgid="5259126567490114216">"<xliff:g id="VALUE">%s</xliff:g> хүрээд, хүлээнэ үү."</string>
@@ -1555,7 +1551,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Нэмэлт сонголтууд"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Дотоод хуваалцсан санах ой"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Дундын дотоод хадгалах сан"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD карт"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD карт"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"USB диск"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 5c6e358..4fb2347 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS मेसेज प्राप्त करण्याची आणि त्यावर प्रक्रिया करण्याची अ‍ॅप ला अनुमती देते. म्हणजेच अ‍ॅप आपल्या डीव्हाइसवर पाठविलेले मेसेज तुम्हाला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"मजकूर मेसेज मिळवा (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS मेसेज प्राप्त करण्यास आणि त्यावर प्रक्रिया करण्यास अ‍ॅप ला अनुमती देते. म्हणजेच अ‍ॅप आपल्या डिव्हाइसवर पाठविलेले मेसेज तुम्हाला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"सेल प्रसारण मेसेज फॉरवर्ड करा"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"सेल प्रसारण मेसेज मिळाल्यानंतर ते फॉरवर्ड करण्यासाठी अॅपला सेल प्रसारण मॉड्यूलमध्ये प्रतिबद्ध करण्याची अनुमती देते. काही स्थानांमध्ये तुम्हाला आणीबाणीच्या परिस्थीतींची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरित केल्या जातात. दुर्भावनापूर्ण अॅप्स आणीबाणी सेल प्रसारण मिळवतात तेव्हा ती तुमच्या डिव्हाइसच्या परफॉर्मन्समध्ये किंवा कामामध्ये कदाचित व्यत्यय आणू शकतात."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"सेल प्रसारण मेसेज वाचा"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"आपल्या डिव्हाइसद्वारे प्राप्त केलेले सेल प्रसारण मेसेज वाचण्यासाठी अ‍ॅप ला अनुमती देते. काही स्थानांमध्ये तुम्हाला आणीबाणीच्या परिस्थितीची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरीत केल्या जातात. आणीबाणी सेल प्रसारण प्राप्त होते तेव्हा आपल्या डिव्हाइसच्या कार्यप्रदर्शनात किंवा कार्यात दुर्भावनापूर्ण अ‍ॅप्स व्यत्यय आणू शकतात."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"सदस्यता घेतलेली फीड वाचा"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"व्यत्यय आणू नका कॉन्फिगरेशन वाचण्यासाठी आणि लिहिण्यासाठी अॅपला अनुमती देते."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"व्ह्यू परवानगी वापर सुरू करा"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"धारकास अ‍ॅपसाठी परवानगी वापरणे सुरू करण्याची अनुमती देते. सामान्य अ‍ॅप्ससाठी कधीही आवश्यकता नसते."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"अॅक्सेसिबिलिटी शॉर्टकट लक्ष्य"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"अ‍ॅपला अॅक्सेसिबिलिटी शॉर्टकट लक्ष्याबद्दल सांगण्यासाठी अनुमती द्या."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियम सेट करा"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्क्रीन लॉक पासवर्ड आणि पिन मध्ये अनुमती दिलेले लांबी आणि वर्ण नियंत्रित करा."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"स्क्रीन अनलॉक प्रयत्नांचे परीक्षण करा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index a7a4c99..4c811fd 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Membenarkan apl menerima dan memproses mesej SMS. Ini bermakna apl boleh memantau atau memadam mesej yang dihantar ke peranti anda tanpa menunjukkannya kepada anda."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"terima mesej teks (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Membenarkan apl menerima dan memproses mesej MMS. Ini bermakna apl boleh memantau atau memadam mesej yang dihantar ke peranti anda tanpa menunjukkannya kepada anda."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Kirim semula mesej siaran sel"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Membenarkan apl terikat pada modul siaran sel untuk mengirim semula mesej siaran sel apabila diterima. Makluman siaran sel dihantar di sesetengah lokasi untuk memberi amaran kepada anda tentang situasi kecemasan. Apl hasad boleh mengganggu prestasi atau operasi peranti anda apabila siaran sel kecemasan diterima."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"baca mesej siaran sel"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Membolehkan apl membaca mesej siaran sel yang diterima oleh peranti anda. Isyarat siaran sel dihantar di beberapa lokasi untuk memberi amaran kepada anda tentang situasi kecemasan. Apl hasad boleh mengganggu prestasi atau operasi peranti anda apabila siaran sel kecemasan diterima."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"baca suapan langganan"</string>
@@ -546,11 +544,11 @@
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Wajah disahkan, sila tekan sahkan"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Perkakasan cap jari tidak tersedia."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Cap jari tidak dapat disimpan. Sila alih keluar cap jari sedia ada."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tamat masa cap jari dicapai. Cuba lagi."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sudah tamat masa untuk cap jari. Cuba lagi"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Pengendalian cap jari dibatalkan."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Pengendalian cap jari dibatalkan oleh pengguna."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Terlalu banyak percubaan. Cuba sebentar lagi."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Terlalu banyak percubaan. Penderia cap jadi dilumpuhkan."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Terlalu banyak percubaan. Penderia cap jari dilumpuhkan."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Cuba lagi."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Tiada cap jari didaftarkan."</string>
     <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Peranti ini tiada penderia cap jari."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Membenarkan apl membaca dan menulis konfigurasi Jangan Ganggu."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"mulakan lihat penggunaan kebenaran"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Membenarkan pemegang memulakan penggunaan kebenaran untuk apl. Tidak sekali-kali diperlukan untuk apl biasa."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"sasaran pintasan kebolehaksesan"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Membenarkan apl mentakrifkan sasaran pintasan kebolehaksesan."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Tetapkan peraturan kata laluan"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan  dan PIN kunci skrin."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Pantau percubaan buka kunci skrin"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index cbe8af4..38a33bf 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -324,7 +324,7 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"မျက်နှာပြင် ဇူးမ်အရွယ်နှင့် နေရာချထားခြင်းကို ထိန်းချုပ်ပါသည်။"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"လက်ဟန်များ အသုံးပြုပါ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"တို့ခြင်း၊ ပွတ်ဆွဲခြင်း၊ နှင့် အခြား လက်ဟန်များကို အသုံးပြုနိုင်ပါသည်။"</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"လက်ဗွေရာများ"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"လက်ဗွေဟန်များ"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"စက်ပစ္စည်း၏ လက်ဗွေအာရုံခံကိရိယာတွင် လုပ်ဆောင်ထားသည့် လက်ဟန်များကို မှတ်သားထားနိုင်သည်။"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"အခြေအနေပြဘားအား အလုပ်မလုပ်ခိုင်းရန်သို့မဟုတ် မွမ်းမံရန်"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"အက်ပ်အား အခြေအနေပြ ဘားကို ပိတ်ခွင့် သို့မဟတ် စနစ် အိုင်ကွန်များကို ထည့်ခြင်း ဖယ်ရှားခြင်း ပြုလုပ်ခွင့် ပြုသည်။"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"အပလီကေးရှင်းအား စာတိုများ လက်ခံခြင်း၊ ဆောင်ရွက်ခြင်း ခွင့်ပြုပါ။ ဤခွင့်ပြုချက်တွင် အပလီကေးရှင်းအနေဖြင့် သင် လက်ခံရရှိသော စာများအား သင့်အား မပြပဲစောင့်ကြည့်ခွင့်နှင့် ဖျက်ပစ်ခွင့်များ ပါဝင်ပါသည်။"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"စာပို့ခြင်းအား လက်ခံရယူခြင်း (ရုပ်သံစာ)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"အပလီကေးရှင်းအား ရုပ်သံစာများ လက်ခံခြင်း၊ ဆောင်ရွက်ခြင်း ခွင့်ပြုပါ။ ဤခွင့်ပြုချက်တွင် အပလီကေးရှင်းအနေဖြင့် သင် လက်ခံရရှိသော စာများအား သင့်အား မပြပဲစောင့်ကြည့်ခွင့်နှင့် ဖျက်ပစ်ခွင့်များ ပါဝင်ပါသည်။"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"စာတို ဖြန့်ဝေခြင်းစနစ်သုံး မက်ဆေ့ဂျ်များကို ထပ်ဆင့်ပို့ခြင်း"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"စာတို ဖြန့်ဝေခြင်းစနစ် မော်ဂျူးကိုပေါင်းရန် အက်ပ်များအား ခွင့်ပြုသည်။ ၎င်းမှာ စာတို ဖြန့်ဝေခြင်းစနစ်သုံး မက်ဆေ့ဂျ်များကို လက်ခံရရှိသည့်အတိုင်း ထပ်ဆင့်ပို့ရန် ဖြစ်သည်။ အချို့တည်နေရာများတွင် သင့်အား အရေးပေါ်အခြေအနေများကို သတိပေးရန် စာတို ဖြန့်ဝေခြင်းစနစ်သုံး သတိပေးချက်များကို ပေးပို့သည်။ အရေးပေါ် စာတို ဖြန့်ဝေခြင်းကို ရရှိသည့်အခါ သံသယဖြစ်နိုင်ဖွယ်ရှိသည့် အက်ပ်များက သင့်စက်၏ စွမ်းဆောင်ရည်နှင့် အော်ပရေးရှင်းတို့ကို အနှောင့်အယှက်ပေးနိုင်သည်။"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"စာတိုများ ဖြန့်ဝေခြင်းစနစ်အား ဖတ်ခြင်း"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"အပလီကေးရှင်းကို သင်၏ စက်ပစ္စည်းမှ လက်ခံရရှိသော အများလွှင့်ထုတ်ချက်များကို ဖတ်ရန် ခွင့်ပြုသည်။  အများလွှင့်ထုတ်ချက်များသည် အရေးပေါ်အခြေအနေများကို သင့်အား သတိပေးရန် အချို့ နေရာများတွင် ပို့ပေးသည်။ အရေးပေါ်သတိပေးချက် ထုတ်လွှင့်ချက်ကို လက်ခံရရှိချိန်တွင်အန္တရာယ် ဖြစ်စေနိုင်သော အပလီကေးရှင်းများသည် သင့်စက်ပစ္စည်း၏ လုပ်ငန်းလည်ပတ်မှုနှင့် စွမ်းဆောင်မှုကို ဝင်စွက်ဖက်နိုင်သည်။"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"အမည်သွင်းထားသောဖိဖ့်များကို ဖတ်ခြင်း"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"ဖုန်းမျက်နှာပြင်လော့ခ်၏ ရှုပ်ထွေးမှုအဆင့် (မြင့်၊ အလယ်အလတ်၊ နိမ့် သို့မဟုတ် မရှိ) အား လေ့လာရန် အက်ပ်ကို ခွင့်ပြုသည်။ ၎င်းက သတ်မှတ်ထားနိုင်သော ဖုန်းမျက်နှာပြင်လော့ခ်၏ စာလုံးရေနှင့် အမျိုးအစားကို ညွှန်ပြပေးသည်။ အသုံးပြုသူများအနေနှင့် ဖုန်းမျက်နှာပြင်လော့ခ်ကို အတိုင်းအတာတစ်ခုအထိ အဆင့်မြှင့်ရန် အက်ပ်က အကြံပြုနိုင်သည်။ သို့သော်လည်း အသုံးပြုသူများက ၎င်းကို ဂရုပြုမနေဘဲ လွတ်လပ်စွာ ကြည့်ရှုနိုင်ပါသည်။ ဖုန်းမျက်နှာပြင်လော့ခ်ကို စာသားအတိုင်း သိမ်းမထားသဖြင့် အက်ပ်သည် စကားဝှက်အစစ်ကို မသိနိုင်ကြောင်း သတိပြုပါ။"</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"ဇီဝဗေဒဆိုင်ရာ အချက်အလက်သုံး ကွန်ပျူတာဆိုင်ရာ စက်ပစ္စည်းကို အသုံးပြုရန်"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"အထောက်အထားစိစစ်ခြင်းအတွက် ဇီဝဗေဒဆိုင်ရာ သတင်းအချက်အလက်များသုံးသည့် ကွန်ပျူတာဆိုင်ရာ စက်ပစ္စည်းကို အသုံးပြုရန် အက်ပ်ကို ခွင့်ပြုသည်"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"လက်ဗွေရာပစ္စည်းကို စီမံမည်"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"အသုံးပြုရန်အတွက် လက်ဗွေရာပုံစံများကို ပေါင်းထည့်ရန် သို့မဟုတ် ဖျက်ရန်နည်းလမ်းများကို အပ်ဖ်အား အသုံးပြုခွင့်ပြုသည်။"</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"လက်ဗွေရာပစ္စည်းကို အသုံးပြုမည်"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"စစ်မှန်ကြောင်းအထောက်အထားပြသခြင်းအတွက် လက်ဗွေရာပစ္စည်းကို အသုံးပြုရန် အပ်ဖ်အားခွင့်ပြုသည်။"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"လက်ဗွေစစ်ပစ္စည်းကို စီမံခြင်း"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"အသုံးပြုရန်အတွက် လက်ဗွေပုံစံများကို ပေါင်းထည့်ရန် သို့မဟုတ် ဖျက်ရန်နည်းလမ်းများကို အပ်က်အား သုံးခွင့်ပြုသည်။"</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"လက်ဗွေ စက်ပစ္စည်းကို အသုံးပြုခြင်း"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"အထောက်အထားစိစစ်ရန်အတွက် အက်ပ်ကို လက်ဗွေစစ်ပစ္စည်း သုံးခွင့်ပြုသည်"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"သင့်တေးဂီတ စုစည်းမှုကို ပြုပြင်ခြင်း"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"အက်ပ်အား သင့်တေးဂီတစုစည်းမှုကို ပြုပြင်ခွင့်ပေးသည်။"</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"သင့်ဗီဒီယို စုစည်းမှုကို ပြုပြင်ခြင်း"</string>
@@ -534,8 +532,8 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"မသိ"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"အထောက်အထားစိစစ်ခြင်းကို ပယ်ဖျက်လိုက်သည်"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"ပင်နံပါတ်၊ လော့ခ်ပုံစံ သို့မဟုတ် စကားဝှက် သတ်မှတ်မထားပါ"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"လက်ဗွေရဦ တစ်ပိုင်းတစ်စ တွေ့ရှိသည်။ ကျေးဇူးပြု၍ ထပ်မံကြိုးစားပါ။"</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"လက်ဗွေရာယူခြင်း မဆောင်ရွက်နိုင်ပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"လက်ဗွေ တစ်ပိုင်းတစ်စ တွေ့ရှိသည်။ ကျေးဇူးပြု၍ ထပ်စမ်းကြည့်ပါ။"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"လက်ဗွေယူ၍ မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"လက်ဗွေဖတ်ကိရိယာ ညစ်ပေနေသည်။ ကျေးဇူးပြု၍ သန့်ရှင်းလိုက်ပြီး ပြန်စမ်းကြည့်ပါ။"</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"လက်ညှိုး အလွန်မြန်ဆန်စွာ ရွေ့ခဲ့သည်။ ထပ်မံ ကြိုးစားပါ။"</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"လက်ညှိုးအလွန်နှေးကွေးစွာ ရွေ့ခဲ့သည်။ ကျေးဇူးပြု၍ ထပ်မံကြိုးစားပါ။"</string>
@@ -544,20 +542,20 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"လက်ဗွေကို အထောက်အထား စိစစ်ပြီးပါပြီ"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ၊ အတည်ပြုရန်ကို နှိပ်ပါ"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"လက်ဗွေရာ ဟာ့ဒ်ဝဲ မရနိုင်ပါ။"</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"လက်ဗွေရာ သိုလှောင်၍မရပါ။ ကျေးဇူးပြု၍ ရှိပြီးလက်ဗွေရာအား ဖယ်ရှားပါ။"</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"လက်ဗွေရာအချိန်ကုန် သွားပါသည်။ ထပ်မံကြိုးစားပါ။"</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"လက်ဗွေရာ လုပ်ငန်း ဖျက်သိမ်းခဲ့၏။"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"လက်ဗွေ စက်ပစ္စည်းမရနိုင်ပါ။"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"လက်ဗွေ သိုလှောင်၍မရပါ။ လက်ရှိ လက်ဗွေကို ဖယ်ရှားပါ။"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"လက်ဗွေယူချိန်ကုန် သွားပါသည်။ ထပ်စမ်းကြည့်ပါ။"</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"လက်ဗွေယူခြင်း ပယ်ဖျက်လိုက်သည်။"</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"လက်ဗွေဖြင့် အထောက်အထားစိစစ်ခြင်းကို အသုံးပြုသူက ပယ်ဖျက်ထားသည်။"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ကြိုးစာမှု အကြိမ်များနေ၏။ နောက်မှ ထပ်မံကြိုးစားပါ။"</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"အကြိမ်အရေအတွက် အလွန်များနေပါပြီ။ လက်ဗွေဖတ်စနစ်ကို ပိတ်ထားပါသည်။"</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"အကြိမ်အရေအတွက် အလွန်များနေပါပြီ။ လက်ဗွေအာရုံခံကိရိယာ ပိတ်ထားပါသည်။"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ပြန်ကြိုးစားပါ"</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"မည်သည့် လက်ဗွေကိုမျှ ထည့်သွင်းမထားပါ။"</string>
     <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"ဤစက်တွင် လက်ဗွေအာရုံခံကိရိယာ မရှိပါ။"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"လက်ချောင်း <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"လက်ဗွေ အိုင်ကွန်"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"လက်ဗွေ သင်္ကေတ"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"မျက်နှာမှတ် သော့ဖွင့်ခြင်း စက်ပစ္စည်းကို စီမံခြင်း"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"အသုံးပြုရန်အတွက် မျက်နှာပုံစံထည့်ရန် (သို့) ဖျက်ရန်နည်းလမ်းကို အက်ပ်အား သုံးခွင့်ပြုသည်။"</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"မျက်နှာမှတ် သော့ဖွင့်ခြင်း စက်ပစ္စည်းကို သုံးပါ"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"မနှောင့်ယှက်ရန် ချိန်ညှိမှုကို အပ်ဖ်များ ဖတ်ခြင်း ပြင်ခြင်းပြုလုပ်နိုင်ရန် ခွင့်ပြုမည်။"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"အစမြင်ကွင်း ခွင့်ပြုချက် အသုံးပြုမှု"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"အက်ပ်တစ်ခုအတွက် ခွင့်ပြုချက်စတင်အသုံးပြုမှုကို ကိုင်ဆောင်သူအား ခွင့်ပြုသည်။ ပုံမှန်အက်ပ်များအတွက် ဘယ်သောအခါမျှ မလိုအပ်ပါ။"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"အများသုံးစွဲနိုင်မှု ဖြတ်လမ်းလင့်ခ် ပစ်မှတ်"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"အများသုံးစွဲနိုင်မှု ဖြတ်လမ်းလင့်ခ် ပစ်မှတ်ကို အက်ပ်အား သတ်မှတ်ခွင့်ပြုသည်။"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"စကားဝှက်စည်းမျဥ်းကိုသတ်မှတ်ရန်"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"မျက်နှာပြင်သော့ခတ်သည့် စကားဝှက်များနှင့် PINများရှိ ခွင့်ပြုထားသည့် စာလုံးအရေအတွက်နှင့် အက္ခရာများအား ထိန်းချုပ်ရန်။"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"မျက်နှာပြင်လော့ခ်ဖွင့်ရန် ကြိုးပမ်းမှုများကို စောင့်ကြည့်ပါ"</string>
@@ -1165,7 +1161,7 @@
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"စနစ် ဆက်တင် ထဲမှာ ပုံသေကို ရှင်းလိုက်ပါ &gt; အက်ပ်များ &gt; ဒေါင်းလုဒ် လုပ်ပြီး။"</string>
     <string name="chooseActivity" msgid="7486876147751803333">"လုပ်စရာ တစ်ခု ရွေးချယ်ပါ"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB ကိရိယာ အတွက် အက်ပ်တစ်ခု ရွေးပါ"</string>
-    <string name="noApplications" msgid="2991814273936504689">"ဘယ် အက်ပ်ကမှ ဒီ လုပ်ဆောင်ချက်ကို မလုပ်ကိုင်နိုင်ပါ။"</string>
+    <string name="noApplications" msgid="2991814273936504689">"မည်သည့်အက်ပ်ကမျှ ဤလုပ်ဆောင်ချက်ကို မလုပ်ကိုင်နိုင်ပါ။"</string>
     <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> ရပ်သွားပါပြီ"</string>
     <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> ရပ်တန့်သွားပါပြီ"</string>
     <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> သည်ထပ်တလဲလဲ ရပ်တန့်နေပါသည်"</string>
@@ -1588,8 +1584,8 @@
     <string name="expires_on" msgid="3676242949915959821">"သက်တမ်းကုန်ဆုံးရက်-"</string>
     <string name="serial_number" msgid="758814067660862493">"အစဉ်လိုက်နံပါတ်"</string>
     <string name="fingerprints" msgid="4516019619850763049">"လက်ပွေများ"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 လက်ပွေ"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 လက်ပွေ"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 လက်ဗွေ-"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 လက်ဗွေ-"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"အားလုံးကို ကြည့်ရန်"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"လုပ်ဆောင်ချက်ကို ရွေးရန်"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"...နှင့် မျှဝေရန်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 183e2e2..2d4a5f5 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Lar appen motta og behandle tekstmeldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til enheten din uten at du har sett dem."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"motta tekstmeldinger (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Lar appen motta og behandle multimediemeldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til enheten din uten at du har sett dem."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Videresend kringkastede meldinger"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Tillat at denne appen binder seg til modulen for kringkastede meldinger for å videresende kringkastede meldinger når de mottas. Kringkastede varsler leveres noen steder for å advare deg om nødssituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lese kringkastede meldinger"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tillater at appen kan lese kringkastede meldinger enheten din mottar. Kringkastede varsler leveres noen steder for å advare deg om nødssituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lese abonnement på nyhetskilder"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Lar appen lese og skrive konfigurasjon av Ikke forstyrr."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"start visning av bruk av tillatelser"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Lar innehaveren starte bruk av tillatelser for en app. Dette skal aldri være nødvendig for vanlige apper."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"mål for tilgjengelighetssnarvei"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Tillat at en app definerer målet for tilgjengelighetssnarveien."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrollerer tillatt lengde og tillatte tegn i passord og PIN-koder for opplåsing av skjermen."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Overvåk forsøk på å låse opp skjermen"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 4c4e1f0..dc44d2a 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -325,7 +325,7 @@
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"इसाराहरू सम्बन्धी कार्य गर्नुहोस्"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ट्याप, स्वाइप गर्न, थिच्न र अन्य इसाराहरू सम्बन्धी कार्य गर्न सक्छ"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"फिंगरप्रिन्टका इसाराहरू"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"यसले यन्त्रक‍ो फिङ्गरप्रिन्टसम्बन्धी सेन्सरमा गरिएका इसाराहरूलाई खिच्‍न सक्छ।"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"यसले यन्त्रक‍ो फिंगरप्रिन्टसम्बन्धी सेन्सरमा गरिएका इसाराहरूलाई खिच्‍न सक्छ।"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"स्थिति पट्टिलाई अक्षम वा संशोधित गर्नुहोस्"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"स्थिति पट्टि असक्षम पार्न वा प्रणाली आइकनहरू थप्न र हटाउन अनुप्रयोगलाई अनुमति दिन्छ।"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"वस्तुस्थिति पट्टी हुन दिनुहोस्"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"अनुप्रयोगलाई SMS सन्देशहरू प्राप्त गर्न र प्रक्रिया गर्न अनुमति दिन्छ। यसको मतलब अनुप्रयोगले तपाईंको उपकरणमा पठाइएको सन्देशहरू तपाईंलाई नदेखाईनै मोनिटर गर्न वा मेटाउन सक्दछ।"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"पाठ सन्देश (MMS) प्राप्त गर्नुहोस्"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"अनुप्रयोगलाई MMS सन्देशहरू प्राप्त गर्न र प्रकृया गर्न अनुमति दिन्छ। यसको मतलब अनुप्रयोगले तपाईंको उपकरणमा पठाइएको सन्देशहरू तपाईंलाई नदेखाईनै मोनिटर गर्न वा मेटाउन सक्दछ।"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"मोबाइल प्रसारणसम्बन्धी सन्देशहरू फर्वार्ड गर्नुहोस्"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"मोबाइल प्रसारणसम्बन्धी सन्देशहरू प्राप्त हुनासाथै तिनीहरूलाई फर्वार्ड गर्नका लागि यसले अनुप्रयोगलाई मोबाइल प्रसारण मोड्युलमा जोडिने अनुमति दिन्छ। तपाईंलाई कतिपय स्थानमा आपत्कालीन अवस्थाका बारेमा जानकारी दिनका लागि मोबाइल प्रसारणसम्बन्धी अलर्टहरू पठाइन्छ। हानिकारक अनुप्रयोगहरूले आपत्कालीन मोबाइल प्रसारण प्राप्त हुँदा तपाईंको यन्त्रलाई कार्य सम्पादन गर्ने वा सञ्चालित हुने क्रममा हस्तक्षेप गर्न सक्छन्।"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"सेल प्रसारित सन्देशहरू पढ्नुहोस्"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"तपाईंको उपकरणद्वारा प्राप्त सेल प्रसारण सन्देशहरू अनुप्रयोगलाई पढ्न अनुमति दिन्छ। सेल प्रसारण चेतावनीहरू केही स्थानहरूमा तपाईंलाई आपतकालीन गतिविधिहरूको बारेमा सचेत गराउन गरिएका छन्। खराब अनुप्रयोगहरूले एउटा आपतकालीन सेल प्रसारण प्राप्त गर्दछ जब तपाईंको उपकरणको प्रदर्शन वा अपरेशनको साथ हस्तक्षेप गर्न सक्दछन्।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"सदस्य बनाइका फिडहरू पढ्नुहोस्"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"यसले अनुप्रयोगलाई स्क्रिन लकको जटिलताको स्तर (उच्च, मध्यम, न्यून वा कुनै पनि होइन) थाहा पाउने अनुमति दिन्छ जसले स्क्रिन लकको लम्बाइको सम्भावित दायरा र त्यसको प्रकारलाई जनाउँछ। यसै गरी, यो अनुप्रयोगले प्रयोगकर्ताहरूलाई स्क्रिन लक अद्यावधिक गर्ने सुझाव पनि दिन सक्छ तर प्रयोगकर्ताहरू उक्त सुझावको बेवास्ता गरी बाहिर निस्कन सक्छन्। स्क्रिन लक सादा पाठको ढाँचामा भण्डारण नगरिने हुँदा यो अनुप्रयोगलाई वास्तविक पासवर्ड थाहा नहुने कुराको हेक्का राख्नुहोस्।"</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"बायोमेट्रिक हार्डवेयर प्रयोग गर्नुहोस्‌"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"अनुप्रयोगलाई प्रमाणीकरणका लागि बायोमेट्रिक हार्डवेयर प्रयोग गर्न अनुमति दिन्छ"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"औठाछाप हार्डवेयर व्यवस्थापन गर्नुहोस्"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"अनुप्रयोगलाई प्रयोगको लागि औठाछाप टेम्प्लेट थप्न र मेटाउने तरिका आह्वान गर्न अनुमति दिन्छ।"</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"औठाछाप हार्डवेयर प्रयोग गर्नुहोस्"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"अनुप्रयोगलाई प्रमाणीकरणको लागि औठाछाप हार्डवेयर प्रयोग गर्न अनुमति दिन्छ"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"फिंगरप्रिन्ट हार्डवेयर व्यवस्थापन गर्नुहोस्"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"अनुप्रयोगलाई प्रयोगको लागि फिंगरप्रिन्ट टेम्प्लेट थप्न र मेटाउने तरिका आह्वान गर्न अनुमति दिन्छ।"</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"फिंगरप्रिन्ट हार्डवेयर प्रयोग गर्नुहोस्"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"यो अनुप्रयोगलाई प्रमाणीकरणको लागि फिंगरप्रिन्ट हार्डवेयर प्रयोग गर्न अनुमति दिन्छ"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"आफ्नो सङ्गीतको सङ्ग्रह परिमार्जन गर्नुहोस्"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"यसले अनुप्रयोगलाई तपाईंको सङ्गीतको सङ्ग्रह परिमार्जन गर्न दिन्छ।"</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"आफ्नो भिडियोको सङ्ग्रह परिमार्जन गर्नुहोस्"</string>
@@ -534,9 +532,9 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"पहिचान भएन"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"प्रमाणीकरण रद्द गरियो"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"कुनै पनि PIN, ढाँचा वा पासवर्ड सेट गरिएको छैन"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक औठाछाप पत्ता लाग्यो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"औठाछाप प्रशोधन गर्न सकिएन। कृपया फेरि प्रयास गर्नुहोस्।"</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"औँठाछाप सेन्सर फोहोर छ। कृपया सफा गरेर फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक फिंगरप्रिन्ट पत्ता लाग्यो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"फिंगरप्रिन्ट प्रशोधन गर्न सकिएन। कृपया फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"फिंगरप्रिन्ट सेन्सर फोहोर छ। कृपया सफा गरेर फेरि प्रयास गर्नुहोस्।"</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"औंला धेरै छिटो चलाइयो। पुन: प्रयास गर्नुहोस्।"</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"औंला निकै सुस्त सारियो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -545,9 +543,9 @@
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"अनुहार प्रमाणीकरण गरियो"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"अनुहार प्रमाणीकरण गरियो, कृपया पुष्टि गर्नुहोस् थिच्नुहोस्"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"औँठाछाप हार्डवेयर उपलब्ध छैन।"</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"औँठाछाप भण्डारण गर्न सकिँदैन। कृपया अवस्थित औठाछाप हटाउनुहोस्।"</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"औँठाछापको समय सकिएको छ। फेरि प्रयास गर्नुहोस्।"</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"औँठाछाप सञ्चालन रद्द गरियो।"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फिंगरप्रिन्ट भण्डारण गर्न सकिँदैन। कृपया अहिलेको फिंगरप्रिन्ट हटाउनुहोस्।"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फिंगरप्रिन्ट समय सकिएको छ। फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"फिंगरप्रिन्ट सञ्चालन रद्द गरियो।"</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"प्रयोगकर्ताले फिंगरप्रिन्टसम्बन्धी कारबाही रद्द गर्नुभयो।"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"धेरै प्रयासहरू। केहि समय पछि पुन: प्रयास गर्नुहोला"</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"अत्यन्त धेरै प्रयासहरू। फिंगरप्रिन्ट सेन्सरलाई असक्षम पारियो।"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"बाधा नपुर्याउँनुहोस् कन्फिगरेसन पढ्न र लेख्‍नको लागि अनुप्रयोगलाई अनुमति दिनुहोस्।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"हेर्ने अनुमतिको प्रयोग सुरु गर्नुहोस्"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"वाहकलाई कुनै अनुप्रयोगसम्बन्धी अनुमतिको प्रयोग सुरु गर्न दिन्छ। साधारण अनुप्रयोगहरूलाई कहिल्यै आवश्यक नपर्नु पर्ने हो।"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"पहुँचसम्बन्धी सर्टकटको लक्ष्य"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"कुनै अनुप्रयोगलाई पहुँचसम्बन्धी सर्टकटको लक्ष्य परिभाषित गर्न दिन्छ।"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियमहरू मिलाउनुहोस्"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्क्रिन लक पासवर्ड र PIN हरूमा अनुमति दिइएको लम्बाइ र वर्णहरूको नियन्त्रण गर्नुहोस्।"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"मनिटरको स्क्रिन अनलक गर्ने प्रयासहरू"</string>
@@ -1594,7 +1590,7 @@
     <string name="serial_number" msgid="758814067660862493">"क्रम संख्या:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"औँठाछापहरू:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-२५६ औंठाछाप:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 औंलाछाप:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 फिंगरप्रिन्ट:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"सबै हेर्नुहोस्"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"गतिविधि छनौट गर्नुहोस्"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"साझेदारी गर्नुहोस्..."</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index b3cc884..5c30c41 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Hiermee kan de app sms-berichten ontvangen en verwerken. Dit betekent dat de app berichten die naar je apparaat zijn verzonden, kan bijhouden of verwijderen zonder deze aan u weer te geven."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"tekstberichten (MMS) ontvangen"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Hiermee kan de app MMS-berichten ontvangen en verwerken. Dit betekent dat de app berichten die naar je apparaat zijn verzonden, kan bijhouden of verwijderen zonder deze aan u weer te geven."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Cell broadcast-berichten doorsturen"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Hiermee kan de app de module voor cell broadcasts binden om cell broadcast-berichten door te sturen als die worden ontvangen. Cell broadcast-waarschuwingen worden op bepaalde locaties verzonden om je te waarschuwen voor noodsituaties. Schadelijke apps kunnen de prestaties of verwerking van je apparaat verstoren als een bericht met een noodmelding wordt ontvangen."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"infodienstberichten lezen"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Toestaan dat de app infodienstberichten leest die worden ontvangen op je apparaat. Infodienstberichten worden verzonden naar bepaalde locaties om u te waarschjeen voor noodsituaties. Schadelijke apps kunnen de prestaties of verwerking van je apparaat verstoren wanneer een infodienstbericht wordt ontvangen."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"Geabonneerde feeds lezen"</string>
@@ -495,9 +493,9 @@
     <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9115646511110555589">"Hiermee kan de app pakketten ontvangen die via multicastadressen naar alle apparaten in een wifi-netwerk worden verzonden, niet alleen naar je Android TV-apparaat. Het stroomgebruik ligt hierbij hoger dan in de niet-multicastmodus."</string>
     <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Hiermee kan de app pakketten ontvangen die via multicastadressen naar alle apparaten in een wifi-netwerk worden verzonden, niet alleen naar je telefoon. Het stroomgebruik ligt hierbij hoger dan in de niet-multicastmodus."</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"Bluetooth-instellingen openen"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Hiermee kan de app de lokale Bluetooth-tablet configureren en externe apparaten zoeken en koppelen."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Hiermee kan de app de lokale bluetooth-tablet configureren en externe apparaten zoeken en koppelen."</string>
     <string name="permdesc_bluetoothAdmin" product="tv" msgid="3174333400857321862">"Hiermee kan de app Bluetooth op je Android TV-apparaat configureren en externe apparaten zoeken en koppelen."</string>
-    <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Hiermee kan de app de lokale Bluetooth-telefoon configureren en externe apparaten zoeken en koppelen."</string>
+    <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Hiermee kan de app de lokale bluetooth-telefoon configureren en externe apparaten zoeken en koppelen."</string>
     <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX-verbinding maken en verbreken"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Hiermee kan de app bepalen of WiMAX is ingeschakeld en informatie bekijken over alle WiMAX-netwerken waarmee verbinding is gemaakt."</string>
     <string name="permlab_changeWimaxState" msgid="340465839241528618">"WiMAX-status wijzigen"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Hiermee kan de app configuratie voor Niet storen lezen en schrijven."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"rechtengebruik starten"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Hiermee kan de houder het rechtengebruik voor een app starten. Nooit vereist voor normale apps."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"doel van snelkoppeling voor toegankelijkheid"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Hiermee kan een app het doel van de snelkoppeling voor toegankelijkheid definiëren."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoordregels instellen"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"De lengte en het aantal tekens beheren die zijn toegestaan in wachtwoorden en pincodes voor schermvergrendeling."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Pogingen voor schermontgrendeling bijhouden"</string>
@@ -1229,10 +1225,10 @@
     <string name="sendText" msgid="5209874571959469142">"Een actie voor tekst selecteren"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Ringtonevolume"</string>
     <string name="volume_music" msgid="5421651157138628171">"Mediavolume"</string>
-    <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Afspelen via Bluetooth"</string>
+    <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Afspelen via bluetooth"</string>
     <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"Stille ringtone ingesteld"</string>
     <string name="volume_call" msgid="3941680041282788711">"Volume inkomend gesprek"</string>
-    <string name="volume_bluetooth_call" msgid="2002891926351151534">"Volume tijdens gesprek in Bluetooth-modus"</string>
+    <string name="volume_bluetooth_call" msgid="2002891926351151534">"Volume tijdens gesprek in bluetooth-modus"</string>
     <string name="volume_alarm" msgid="1985191616042689100">"Wekkervolume"</string>
     <string name="volume_notification" msgid="2422265656744276715">"Meldingsvolume"</string>
     <string name="volume_unknown" msgid="1400219669770445902">"Volume"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index eb8f4c6..ac85a40 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -324,8 +324,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ଡିସପ୍ଲେର ଜୁମ୍‍ ସ୍ତର ଓ ପୋଜିସନିଙ୍ଗ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ଜେଶ୍ଚର୍‍ କରନ୍ତୁ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ଟାପ୍‍, ସ୍ୱାଇପ୍‍, ପିଞ୍ଚ ଓ ଅନ୍ୟାନ୍ୟ ଜେଶ୍ଚର୍‍ ସମ୍ପାଦନ କରିପାରିବ।"</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଜେଶ୍ଚର"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ଡିଭାଇସ୍‌ର ଆଙ୍ଗୁଠି ଚିହ୍ନ ସେନସର୍ ଉପରେ ଜେଶ୍ଚର୍‍ କ୍ୟାପଚର୍‍ କାର୍ଯ୍ୟ କରାଯାଇପାରିବ।"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ଟିପଚିହ୍ନ ଜେଶ୍ଚର"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ଡିଭାଇସ୍‌ର ଟିପଚିହ୍ନ ସେନସର୍ ଉପରେ ଜେଶ୍ଚର୍‍ କ୍ୟାପଚର୍‍ କାର୍ଯ୍ୟ କରାଯାଇପାରିବ।"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"ଷ୍ଟାଟସ୍‌ ବାର୍‌କୁ ଅକ୍ଷମ କିମ୍ୱା ସଂଶୋଧନ କରନ୍ତୁ"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"ଆପ୍‍କୁ, ସ୍ଥିତି ବାର୍‍ ଅକ୍ଷମ କରିବାକୁ କିମ୍ବା ସିଷ୍ଟମ୍‍ ଆଇକନ୍‍ ଯୋଡ଼ିବା କିମ୍ବା ବାହାର କରିବାକୁ ଦେଇଥାଏ।"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ଷ୍ଟାଟସ୍‍ ବାର୍‍ ରହିବାକୁ ଦିଅନ୍ତୁ"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS ମେସେଜ୍‌ ପ୍ରାପ୍ତ କରିବାକୁ ତଥା ପ୍ରକ୍ରିୟା କରାଇବାକୁ ଆପ୍‍ଟିକୁ ଅନୁମତି ଦିଏ। ଏହାର ଅର୍ଥ ହେଉଛି, ଆପଣଙ୍କ ଡିଭାଇସ୍‍କୁ ପଠାଯାଇଥିବା ମେସେଜ୍‍ ଆପଣଙ୍କୁ ନଦେଖାଇ ଆପ୍‍ଟି ମନିଟର୍‍ କିମ୍ବା ଡିଲିଟ୍‍ କରିପାରେ।"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ଟେକ୍ସଟ୍‍ ମେସେଜ୍‍ (MMS) ପ୍ରାପ୍ତ କରନ୍ତୁ"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS ମେସେଜ୍‌ ପ୍ରାପ୍ତ କରିବାକୁ ତଥା ପ୍ରକ୍ରିୟା କରାଇବାକୁ ଆପ୍‍ଟିକୁ ଅନୁମତି ଦିଏ। ଏହାର ଅର୍ଥ, ଆପଣଙ୍କ ଡିଭାଇସ୍‍କୁ ପଠାଯାଇଥିବା ମେସେଜ୍‍ ଆପଣଙ୍କୁ ନଦେଖାଇ ଆପ୍‍ଟି ମନିଟର୍‍ କିମ୍ବା ଡିଲିଟ୍‍ କରିପାରେ।"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"ସେଲ୍ ପ୍ରସାରଣ ମେସେଜ୍ ଫର୍‍ୱାର୍ଡ କରନ୍ତୁ"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"ସେଲ୍ ପ୍ରସାରଣ ମେସେଜ୍ ପ୍ରାପ୍ତ ହେବା ପରେ ସେଗୁଡ଼ିକୁ ଫର୍‍ୱାର୍ଡ କରିବା ପାଇଁ ଆପ୍‍କୁ ସେଲ୍ ପ୍ରସାରଣ ମଡ୍ୟୁଲ୍ ସହିତ ସଂଯୁକ୍ତ କରିବାକୁ ଅନୁମତି ଦିଏ। ଜରୁରୀକାଳୀନ ପରିସ୍ଥିତିରେ ଆପଣଙ୍କୁ ଚେତାବନୀ ଦେବା ପାଇଁ କିଛି ଲୋକେସନ୍‍‍ରେ ସେଲ୍ ପ୍ରସାରଣ ଆଲର୍ଟ ବିତରଣ କରାଯାଇଥାଏ। ଏକ ଜରୁରୀକାଳୀନ ସେଲ୍ ପ୍ରସାରଣ ପ୍ରାପ୍ତ ହେବା ସମୟରେ କିଛି କ୍ଷତିକାରକ ଆପ୍ସ ହୁଏତ ଆପଣଙ୍କର ଡିଭାଇସ୍‍ର କାର୍ଯ୍ୟଦକ୍ଷତା କିମ୍ବା କାର୍ଯ୍ୟ ପ୍ରକ୍ରିୟାରେ ହସ୍ତକ୍ଷେପ କରିପାରେ।"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ମେସେଜ୍‍ ପଢ଼ନ୍ତୁ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ଆପଣଙ୍କ ଡିଭାଇସ୍‍ରେ ପ୍ରାପ୍ତ ହୋଇଥିବା ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ମେସେଜ୍‍ ପଢିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। ଜରୁରୀକାଳୀନ ଅବସ୍ଥା ବିଷୟରେ ଆପଣଙ୍କୁ ସତର୍କ କରାଇବାକୁ କିଛି ଲୋକେଶନ୍‍ରେ ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ସତର୍କ ଡେଲିଭର୍ କରାଯାଇଥାଏ। ଏକ ଜରୁରୀକାଳୀନ ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ପ୍ରାପ୍ତ ହେବାପରେ ହାନୀକାରକ ଆପ୍‍ ଆପଣଙ୍କ ଡିଭାଇସ୍‍ର କାର୍ଯ୍ୟକ୍ଷମତା କିମ୍ବା ସଞ୍ଚାଳନାରେ ବାଧା ପହଞ୍ଚାଇପାରନ୍ତି।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ସବସ୍କ୍ରାଇବ୍ ହୋଇଥିବା ଫୀଡ୍‌କୁ ପଢ଼ନ୍ତୁ"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"ସ୍କ୍ରିନ୍ ଲକ୍‌ର ଜଟିଳତା ସ୍ତର (ଉଚ୍ଚ, ମଧ୍ୟମ, ନିମ୍ନ କିମ୍ବା କିଛିନୁହେଁ), ଜାଣିବାକୁ ଆପ୍‌କୁ ଅନୁମତି ଦିଅନ୍ତୁ, ଯାହା ସ୍କ୍ରିନ୍ ଲକ୍‌ର ସମ୍ଭାବ୍ୟ ପରିସୀମାର ଲମ୍ବ ଏବଂ ପ୍ରକାର ସୂଚୀତ କରେ। ଆପ୍ ଏହା ମଧ୍ୟ ଉପଯୋଗକର୍ତ୍ତାମାନଙ୍କୁ ପରାମର୍ଶ ଦେଇପାରେ ଯେ ସେମାନେ ସ୍କ୍ରିନ୍ ଲକ୍‌କୁ ଏକ ନିର୍ଦ୍ଧିଷ୍ଟ ସ୍ତର ପର୍ଯ୍ୟନ୍ତ ଅପ୍‌ଡେଟ୍ କରିପାରନ୍ତି, କିନ୍ତୁ ଉପଯୋଗକର୍ତ୍ତାମାନେ ନିଜ ଇଚ୍ଛାରେ ଏହାକୁ ଉପେକ୍ଷା ଏବଂ ନାଭିଗେଟ୍ କରିପାରିବେ। ଧ୍ୟାନ ଦିଅନ୍ତୁ ଯେ, ସ୍କ୍ରିନ୍ ଲକ୍ ସରଳ ଟେକ୍ସଟ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇନଥାଏ ତେଣୁ ଆପ୍ ସଠିକ୍ ପାସ୍‌‍ୱର୍ଡ ଜାଣିପାରି ନଥାଏ।"</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"ବାୟୋମେଟ୍ରିକ୍‌ ହାର୍ଡୱେର୍‌ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"ସ୍ୱୀକୃତି ପାଇଁ ବାୟୋମେଟ୍ରିକ୍‌ ହାର୍ଡୱେର୍‌ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦିଏ"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍‍ ପରିଚାଳନା କରନ୍ତୁ"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ବ୍ୟବହାର କରିବା ପାଇଁ ଆଙ୍ଗୁଠି ଚିହ୍ନ ଯୋଡ଼ିବାକୁ ଓ ଡିଲିଟ୍‍ କରିବାକୁ ଆପକୁ ବିଧି ଆରମ୍ଭ କରିବାକୁ ଦେଇଥାଏ।"</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍‍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ସ୍ୱୀକୃତି ପାଇଁ ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍‍ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦିଏ"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ଟିପଚିହ୍ନ ହାର୍ଡୱେର୍‍ ପରିଚାଳନା କରନ୍ତୁ"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ବ୍ୟବହାର କରିବା ପାଇଁ ଟିପଚିହ୍ନ ଟେମ୍ପ୍ଲେଟ୍ ଯୋଡ଼ିବାକୁ ଓ ଡିଲିଟ୍‍ କରିବାକୁ ଆପକୁ ପ୍ରକ୍ରିୟା ଆରମ୍ଭ କରିବାକୁ ଦେଇଥାଏ।"</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"ଟିପଚିହ୍ନ ହାର୍ଡୱେର୍‍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ପ୍ରମାଣିକରଣ ପାଇଁ ଟିପଚିହ୍ନ ହାର୍ଡୱେର୍‍ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦିଏ"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"ଆପଣଙ୍କ ସଙ୍ଗୀତ ସଂଗ୍ରହ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"ଆପଣ ଆପଣଙ୍କ ସଙ୍ଗୀତ ସଂଗ୍ରହ ପରିବର୍ତ୍ତନ କରିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"ଆପଣଙ୍କ ଭିଡିଓ ସଂଗ୍ରହ ସଂଶୋଧନ କରନ୍ତୁ"</string>
@@ -534,30 +532,30 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"ଚିହ୍ନଟ ହେଲାନାହିଁ"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"ପ୍ରାମାଣିକତାକୁ ବାତିଲ୍ କରାଯାଇଛି"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"କୌଣସି ପିନ୍, ପେଟେର୍ନ ବା ପାସ୍‍ୱର୍ଡ ସେଟ୍ ନାହିଁ"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଆଂଶିକ ଚିହ୍ନଟ ହେଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ଆଂଶିକ ଟିପଚିହ୍ନ ଚିହ୍ନଟ ହେଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ଟିପଚିହ୍ନ ପ୍ରୋସେସ୍‍ କରାଯାଇପାରିଲା ନାହିଁ। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ଟିପଚିହ୍ନ ସେନ୍ସର୍‍ ମଇଳା ହୋଇଯାଇଛି। ଦୟାକରି ସଫା କରନ୍ତୁ ଓ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"ଆଙ୍ଗୁଠି ବହୁତ ଜୋର୍‌ରେ ଚଲାଗଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ଆଙ୍ଗୁଠି ଖୁବ୍‍ ଧୀରେ ନିଆଗଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="5309333983002526448">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ପ୍ରମାଣୀକୃତ ହେଲା"</string>
+    <string name="fingerprint_authenticated" msgid="5309333983002526448">"ଟିପଚିହ୍ନ ପ୍ରମାଣିତ ହେଲା"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ମୁହଁ ଚିହ୍ନଟ ହୋଇଛି"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ମୁହଁ ଚିହ୍ନଟ ହୋଇଛି, ଦୟାକରି ସୁନିଶ୍ଚିତ ଦବାନ୍ତୁ"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍‍ ଉପଲବ୍ଧ ନାହିଁ।"</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଷ୍ଟୋର୍‍ କରାଯାଇପାରିବ ନାହିଁ। ଦୟାକରି ପୂର୍ବରୁ ଥିବା ଆଙ୍ଗୁଠି ଚିହ୍ନକୁ ବାହାର କରିଦିଅନ୍ତୁ।"</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ଆଙ୍ଗୁଠି ଚିହ୍ନର ସମୟ ଶେଷ ହେଲା । ପୁଣିଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ଆଙ୍ଗୁଠି ଚିହ୍ନ କାର୍ଯ୍ୟ କ୍ୟାନ୍ସଲ୍‍ କରାଗଲା।"</string>
-    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ୟୁଜର୍‌ଙ୍କ ଦ୍ଵାରା ଆଙ୍ଗୁଠି ଚିହ୍ନ ନେବା କାମକୁ କ୍ୟାନ୍ସଲ୍ କରିଦିଆଯାଇଛି।"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ଟିପଚିହ୍ନ ହାର୍ଡୱେର୍‍ ଉପଲବ୍ଧ ନାହିଁ।"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ଟିପଚିହ୍ନ ଷ୍ଟୋର୍‍ କରାଯାଇପାରିବ ନାହିଁ। ଦୟାକରି ପୂର୍ବରୁ ଥିବା ଟିପଚିହ୍ନକୁ କାଢ଼ି ଦିଅନ୍ତୁ।"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ଟିପଚିହ୍ନର ସମୟ ଶେଷ ହେଲା । ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ଟିପଚିହ୍ନ କାର୍ଯ୍ୟ ବାତିଲ୍ କରାଗଲା।"</string>
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ଉପଯୋଗକର୍ତ୍ତା ଟିପଚିହ୍ନ କାର୍ଯ୍ୟ ବାତିଲ୍ କରିଛନ୍ତି।"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ବହୁତ ପ୍ରୟାସ କରାଗଲା। ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ବହୁତ ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଙ୍ଗୁଠି ଚିହ୍ନ ସେନ୍ସର୍‍ ଅକ୍ଷମ କରାଗଲା।"</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ବହୁଥର ପ୍ରୟାସ କରିଛନ୍ତି। ଟିପଚିହ୍ନ ସେନ୍ସର୍‍ ଅକ୍ଷମ କରାଯାଇଛି।"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"କୌଣସି ଆଙ୍ଗୁଠି ଚିହ୍ନ ପଞ୍ଜୀକୃତ ହୋଇନାହିଁ।"</string>
     <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"ଏହି ଡିଭାଇସ୍‌ରେ ଟିପଚିହ୍ନ ସେନ୍‍ସର୍ ନାହିଁ।"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ଆଙ୍ଗୁଠି <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଆଇକନ୍"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ଟିପଚିହ୍ନ ଆଇକନ୍"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"ଫେସ୍ ଅନ୍‌ଲକ୍ ହାର୍ଡୱେର୍ ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"ବ୍ୟବହାର ପାଇଁ ଆପ୍‍କୁ ଫେସିଆଲ୍‍ ଟେମ୍ପଲେଟ୍‍ ଯୋଡିବା ଓ ଡିଲିଟ୍‍ ର ପଦ୍ଧତି ପାଇଁ ଅନୁମତି ଦିଅନ୍ତୁ।"</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"ଫେସ୍ ଅନ୍‌ଲକ୍ ହାର୍ଡୱେର୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" କନଫିଗରେଶନ୍‍ ପଢ଼ିବା ତଥା ଲେଖିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"ଅନୁମତି ବ୍ୟବହାର ଦେଖିବା ଆରମ୍ଭ କରନ୍ତୁ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ଏକ ଆପ୍ ପାଇଁ ଅନୁମତିର ବ୍ୟବହାର ଆରମ୍ଭ କରିବାକୁ ଧାରକକୁ ଅନୁମତି ଦେଇଥାଏ। ସାଧାରଣ ଆପ୍‌ଗୁଡ଼ିକ ପାଇଁ ଏହା ଆବଶ୍ୟକ ନୁହେଁ।"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ଆକ୍ସେସିବିଲିଟୀ ସର୍ଟକଟ୍ ଟାର୍ଗେଟ୍"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ଆକ୍ସେସିବିଲିଟୀ ସର୍ଟକଟ୍ ଟାର୍ଗେଟ୍ ବ୍ୟାଖ୍ୟା କରିବା ପାଇଁ ଯେ କୌଣସି ଆପ୍‍କୁ ଅନୁମତି ଦିଏ।"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ପାସ୍‌ୱର୍ଡ ନିୟମାବଳୀ ସେଟ୍ କରନ୍ତୁ"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"ଲକ୍‍ ସ୍କ୍ରୀନ୍‍ ପାସ୍‌ୱର୍ଡ ଓ PINରେ ଅନୁମୋଦିତ ଦୀର୍ଘତା ଓ ବର୍ଣ୍ଣ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"ସ୍କ୍ରୀନ୍-ଅନଲକ୍ କରିବା ଉଦ୍ୟମ ନୀରିକ୍ଷଣ କରନ୍ତୁ"</string>
@@ -1588,7 +1584,7 @@
     <string name="serial_number" msgid="758814067660862493">"କ୍ରମିକ ସଂଖ୍ୟା:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"ଆଙ୍ଗୁଠି ଚିହ୍ନ:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ଆଙ୍ଗୁଠି ଚିହ୍ନ:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ଆଙ୍ଗୁଠି ଚିହ୍ନ:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ଟିପଚିହ୍ନ:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"ସମସ୍ତ ଦେଖନ୍ତୁ"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"ଗତିବିଧି ଚୟନ କରନ୍ତୁ"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"ଏହାଙ୍କ ସହ ସେୟାର୍‍ କରନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index bc68885..177c7bc 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"ਐਪ ਨੂੰ SMS ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸਦਾ ਮਤਲਬ ਹੈ ਕਿ ਐਪ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੇ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਨੂੰ ਤੁਹਾਨੂੰ ਦਿਖਾਏ ਬਿਨਾਂ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ ਜਾਂ ਮਿਟਾ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ਟੈਕਸਟ ਸੁਨੇਹੇ (MMS) ਪੜ੍ਹੋ"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"ਐਪ ਨੂੰ MMS ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸਦਾ ਮਤਲਬ ਹੈ ਕਿ ਐਪ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੇ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਨੂੰ ਤੁਹਾਨੂੰ ਦਿਖਾਏ ਬਿਨਾਂ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ ਜਾਂ ਮਿਟਾ ਸਕਦੀ ਹੈ।"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹਿਆਂ ਨੂੰ ਅੱਗੇ ਭੇਜੋ"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"ਐਪ ਨੂੰ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹਿਆਂ ਦੇ ਪ੍ਰਾਪਤ ਹੁੰਦੇ ਹੀ ਉਹਨਾਂ ਨੂੰ ਅੱਗੇ ਭੇਜਣ ਲਈ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਮਾਡਿਊਲ ਨਾਲ ਜੋੜਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ। ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਚੇਤਨਾਵਾਂ ਤੁਹਾਨੂੰ ਸੰਕਟਕਾਲੀ ਸਥਿਤੀਆਂ ਦੀ ਚਿਤਾਵਨੀ ਦੇਣ ਲਈ ਕੁਝ ਟਿਕਾਣਿਆਂ \'ਤੇ ਪ੍ਰਦਾਨ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਭੈੜੀਆਂ ਐਪਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਕਾਰਗੁਜ਼ਾਰੀ ਜਾਂ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਇੱਕ ਸੰਕਟਕਾਲੀ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ਸੈਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹੇ ਪੜ੍ਹੋ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਵੱਲੋਂ ਪ੍ਰਾਪਤ ਕੀਤੇ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਸੁਨੇਹੇ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਚਿਤਾਵਨੀਆਂ ਤੁਹਾਨੂੰ ਸੰਕਟਕਾਲੀਨ ਸਥਿਤੀਆਂ ਦੀ ਚਿਤਾਵਨੀ ਦੇਣ ਲਈ ਕੁਝ ਨਿਰਧਾਰਤ ਟਿਕਾਣਿਆਂ ਤੇ ਪ੍ਰਦਾਨ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਪ੍ਰਦਰਸ਼ਨ ਜਾਂ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਇੱਕ ਸੰਕਟਕਾਲੀਨ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ਸਬਸਕ੍ਰਾਈਬ ਕੀਤੇ ਫੀਡਸ ਪੜ੍ਹੋ"</string>
@@ -544,10 +542,10 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ, ਕਿਰਪਾ ਕਰਕੇ \'ਪੁਸ਼ਟੀ ਕਰੋ\' ਦਬਾਓ"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ।"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ। ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਮੌਜੂਦਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਟਾਓ।"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਗਿਆ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ਫਿੰਗਰ"</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਓਪਰੇਸ਼ਨ ਰੱਦ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਓਪਰੇਸ਼ਨ ਵਰਤੋਂਕਾਰ ਵੱਲੋਂ ਰੱਦ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ਬਹੁਤ ਸਾਰੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ. ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ਹੱਦੋਂ ਵੱਧ ਕੋਸ਼ਿਸ਼ਾਂ। ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ।"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"ਐਪ ਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ ਕੌਂਫਿਗਰੇਸ਼ਨ ਨੂੰ ਪੜ੍ਹਨ ਅਤੇ ਲਿਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"ਇਜਾਜ਼ਤ ਵਰਤੋਂ ਦੇਖਣਾ ਸ਼ੁਰੂ ਕਰੋ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ਧਾਰਕ ਨੂੰ ਕਿਸੇ ਹੋਰ ਐਪ ਲਈ ਇਜਾਜ਼ਤ ਵਰਤੋਂ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਦਿੰਦਾ ਹੈ। ਸਧਾਰਨ ਐਪਾਂ ਲਈ ਕਦੇ ਵੀ ਲੋੜੀਂਦਾ ਨਹੀਂ ਹੋਵੇਗਾ।"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਟੀਚਾ"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ਕਿਸੇ ਐਪ ਨੂੰ ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਟੀਚੇ ਨੂੰ ਪਰਿਭਾਸ਼ਿਤ ਕਰਨ ਦਿਓ।"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ਪਾਸਵਰਡ ਨਿਯਮ ਸੈੱਟ ਕਰੋ"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"ਸਕ੍ਰੀਨ ਲਾਕ ਪਾਸਵਰਡਾਂ ਅਤੇ ਪਿੰਨ ਵਿੱਚ ਆਗਿਆ ਦਿੱਤੀ ਲੰਮਾਈ ਅਤੇ ਅੱਖਰਾਂ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ।"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"ਸਕ੍ਰੀਨ ਅਣਲਾਕ ਕਰਨ ਦੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ \'ਤੇ ਨਿਗਰਾਨੀ ਰੱਖੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 1dbe1c1..1f2430c 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -234,7 +234,7 @@
     <string name="global_action_bug_report" msgid="7934010578922304799">"Zgłoszenie błędu"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Zakończ sesję"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"Zrzut ekranu"</string>
-    <string name="bugreport_title" msgid="5981047024855257269">"Zgłoszenie błędu"</string>
+    <string name="bugreport_title" msgid="5981047024855257269">"Zgłoś błąd"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Informacje o bieżącym stanie urządzenia zostaną zebrane i wysłane e-mailem. Przygotowanie zgłoszenia błędu do wysłania chwilę potrwa, więc zachowaj cierpliwość."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Raport interaktywny"</string>
     <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"Używaj tej opcji w większości przypadków. Umożliwia śledzenie postępów raportu, podanie dodatkowych szczegółów problemu i wykonanie zrzutów ekranu. Raport może pomijać niektóre rzadko używane sekcje, których utworzenie zajmuje dużo czasu."</string>
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Pozwala aplikacji na odbieranie i przetwarzanie SMS-ów. To oznacza, że aplikacja będzie mogła bez Twojej wiedzy monitorować i usuwać wiadomości wysyłane do Twojego urządzenia."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"odbieranie wiadomości tekstowych (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Pozwala aplikacji na odbieranie i przetwarzanie MMS-ów. To oznacza, że aplikacja będzie mogła bez Twojej wiedzy monitorować i usuwać wiadomości wysyłane do Twojego urządzenia."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Przekaż komunikaty z sieci komórkowej"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Zezwala aplikacji powiązać się z modułem komunikatów z sieci komórkowej, aby przekazywać je w momencie, w którym są otrzymywane. W niektórych lokalizacjach komunikaty alarmowe z sieci komórkowej są dostarczane, aby ostrzec Cię o sytuacjach zagrożenia. Złośliwe aplikacje mogą wpływać na działanie urządzenia lub zakłócać je po nadejściu komunikatu alarmowego z sieci komórkowej."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"odczyt komunikatów z sieci komórkowej"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Zezwala aplikacji na odczyt komunikatów z sieci komórkowej odebranych na urządzeniu. Komunikaty alarmowe z sieci komórkowej są dostarczane w niektórych lokalizacjach w celu ostrzeżenia Cię o sytuacjach zagrożenia. Złośliwe aplikacje mogą wpływać na wydajność lub zakłócać działanie urządzenia po odebraniu komunikatu alarmowego z sieci komórkowej."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"czytanie subskrybowanych źródeł"</string>
@@ -552,7 +550,7 @@
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Twarz rozpoznana, kliknij Potwierdź"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Czytnik linii papilarnych nie jest dostępny."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Nie można zapisać odcisku palca. Usuń istniejący odcisk palca."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Osiągnięto limit czasu odczytu linii papilarnych. Spróbuj ponownie."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Osiągnięto limit czasu odczytu odcisków palców. Spróbuj ponownie."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Odczyt odcisku palca został anulowany."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Odczyt odcisku palca został anulowany przez użytkownika."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Zbyt wiele prób. Spróbuj ponownie później."</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Pozwala aplikacji na odczyt i zmianę konfiguracji trybu Nie przeszkadzać."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"rozpocząć wyświetlanie użycia uprawnień"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Umożliwia rozpoczęcie korzystania z uprawnienia dotyczącego danej aplikacji jego posiadaczowi. Zwykłe aplikacje nie powinny potrzebować tego uprawnienia."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cel skrótu do ułatwień dostępu"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Pozwala aplikacji definiować cel skrótu do ułatwień dostępu."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolowanie długości haseł blokady ekranu i kodów PIN oraz dozwolonych w nich znaków."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitorowanie prób odblokowania ekranu"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index c5bcb1d..05967af 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -237,8 +237,8 @@
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Relatório completo"</string>
     <string name="bugreport_option_full_summary" msgid="7210859858969115745">"Use esta opção para ter o mínimo de interferência do sistema quando seu dispositivo não estiver respondendo ou estiver muito lento, ou quando você precisar de todas as seções de relatórios. Ela não permite que você informe mais detalhes ou faça capturas de tela adicionais."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
-      <item quantity="one">Capturas de tela para o relatório do bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
-      <item quantity="other">Capturas de tela para o relatório do bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
+      <item quantity="one">Capturas de tela para o relatório de bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
+      <item quantity="other">Capturas de tela para o relatório de bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
     </plurals>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modo silencioso"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Som DESATIVADO"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que o app receba e processe mensagens SMS. Isso significa que o app pode monitorar ou excluir mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receber mensagens de texto (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite que o app receba e processe mensagens MMS. Isso significa que o app pode monitorar ou excluir as mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Encaminhar mensagens de transmissão celular"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite que o app se vincule ao módulo de transmissão celular para encaminhar mensagens de transmissão celular assim que elas forem recebidas. Alertas de transmissão celular são recebidos em alguns locais para avisar sobre situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento do dispositivo quando uma transmissão celular de emergência é recebida."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ler mensagens de difusão celular"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite que o app leia mensagens de difusão celular recebidas por seu dispositivo. Alertas de difusão celular são recebidos em alguns locais para avisar você de situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento de seu dispositivo quando uma difusão celular de emergência é recebida."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ler feeds inscritos"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permitir que o app leia e grave a configuração \"Não perturbe\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"iniciar uso da permissão para visualização"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite que o sistema inicie o uso de permissão para um app. Não deve ser necessário para apps comuns."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"objetivo do atalho de acessibilidade"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite que um app defina o objetivo do atalho de acessibilidade."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controla o tamanho e os caracteres permitidos nos PINs e nas senhas do bloqueio de tela."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitorar tentativas de desbloqueio de tela"</string>
@@ -1373,10 +1369,10 @@
     <string name="usb_contaminant_detected_message" msgid="832337061059487250">"A porta USB é desativada automaticamente. Toque para saber mais."</string>
     <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"É seguro usar a porta USB"</string>
     <string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Não há mais líquidos ou detritos detectados no smartphone."</string>
-    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
-    <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
-    <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório do bug…"</string>
-    <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"Seu administrador solicitou um relatório do bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório de bug..."</string>
+    <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório de bug?"</string>
+    <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório de bug…"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"Seu administrador solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
     <string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTILHAR"</string>
     <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECUSAR"</string>
     <string name="select_input_method" msgid="4653387336791222978">"Selecione o método de entrada"</string>
@@ -1555,7 +1551,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Mais opções"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Armazenamento interno compartilhado"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Divisão interna de armazenamento"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Cartão SD"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"Cartão SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"Drive USB"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 29ef549..400d576 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que a aplicação receba e processe mensagens SMS. Isto significa que a aplicação poderá monitorizar ou eliminar mensagens enviadas para o seu dispositivo sem as apresentar."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receber mensagens de texto (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite que a aplicação receba e processe mensagens MMS. Isto significa que a aplicação poderá monitorizar ou eliminar mensagens enviadas para o seu dispositivo sem as apresentar."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Encaminhar mensagens de difusão celular"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite que a aplicação se vincule ao módulo de difusão celular para encaminhar mensagens de difusão celular à medida que são recebidas. Os alertas de difusão celular são fornecidos em algumas localizações para avisar sobre situações de emergência. As aplicações maliciosas podem interferir com o desempenho ou funcionamento do seu dispositivo quando for recebida uma difusão celular de emergência."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ler mensagens de transmissão celular"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite que a aplicação leia mensagens de transmissão celular recebidas pelo seu dispositivo. Os alertas de transmissão celular são fornecidos em algumas localizações para avisá-lo sobre situações de emergência. As aplicações maliciosas podem interferir com o desempenho ou funcionamento do seu dispositivo quando for recebida uma transmissão celular de emergência."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ler feeds subscritos"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permite à aplicação ler e alterar a configuração de Não incomodar"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"iniciar utilização da autorização de visualização"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite que o titular inicie a utilização de autorizações para uma aplicação. Nunca deverá ser necessário para aplicações normais."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"alvo do atalho de acessibilidade"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite a uma aplicação definir o alvo do atalho de acessibilidade."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras de palavra-passe"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controlar o comprimento e os carateres permitidos nos PINs e nas palavras-passe do bloqueio de ecrã."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitorizar tentativas de desbloqueio do ecrã"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index c5bcb1d..05967af 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -237,8 +237,8 @@
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Relatório completo"</string>
     <string name="bugreport_option_full_summary" msgid="7210859858969115745">"Use esta opção para ter o mínimo de interferência do sistema quando seu dispositivo não estiver respondendo ou estiver muito lento, ou quando você precisar de todas as seções de relatórios. Ela não permite que você informe mais detalhes ou faça capturas de tela adicionais."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
-      <item quantity="one">Capturas de tela para o relatório do bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
-      <item quantity="other">Capturas de tela para o relatório do bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
+      <item quantity="one">Capturas de tela para o relatório de bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
+      <item quantity="other">Capturas de tela para o relatório de bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
     </plurals>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modo silencioso"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Som DESATIVADO"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que o app receba e processe mensagens SMS. Isso significa que o app pode monitorar ou excluir mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receber mensagens de texto (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite que o app receba e processe mensagens MMS. Isso significa que o app pode monitorar ou excluir as mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Encaminhar mensagens de transmissão celular"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite que o app se vincule ao módulo de transmissão celular para encaminhar mensagens de transmissão celular assim que elas forem recebidas. Alertas de transmissão celular são recebidos em alguns locais para avisar sobre situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento do dispositivo quando uma transmissão celular de emergência é recebida."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ler mensagens de difusão celular"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite que o app leia mensagens de difusão celular recebidas por seu dispositivo. Alertas de difusão celular são recebidos em alguns locais para avisar você de situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento de seu dispositivo quando uma difusão celular de emergência é recebida."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ler feeds inscritos"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permitir que o app leia e grave a configuração \"Não perturbe\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"iniciar uso da permissão para visualização"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite que o sistema inicie o uso de permissão para um app. Não deve ser necessário para apps comuns."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"objetivo do atalho de acessibilidade"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite que um app defina o objetivo do atalho de acessibilidade."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controla o tamanho e os caracteres permitidos nos PINs e nas senhas do bloqueio de tela."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitorar tentativas de desbloqueio de tela"</string>
@@ -1373,10 +1369,10 @@
     <string name="usb_contaminant_detected_message" msgid="832337061059487250">"A porta USB é desativada automaticamente. Toque para saber mais."</string>
     <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"É seguro usar a porta USB"</string>
     <string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Não há mais líquidos ou detritos detectados no smartphone."</string>
-    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
-    <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
-    <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório do bug…"</string>
-    <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"Seu administrador solicitou um relatório do bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório de bug..."</string>
+    <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório de bug?"</string>
+    <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório de bug…"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"Seu administrador solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
     <string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTILHAR"</string>
     <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECUSAR"</string>
     <string name="select_input_method" msgid="4653387336791222978">"Selecione o método de entrada"</string>
@@ -1555,7 +1551,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Mais opções"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Armazenamento interno compartilhado"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Divisão interna de armazenamento"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Cartão SD"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"Cartão SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"Drive USB"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 8ee45f9..27e6ec0 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -347,10 +347,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite aplicației să primească și să proceseze mesaje SMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"primește mesaje text (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite aplicației să primească și să proceseze mesaje MMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Redirecționează mesajele cu transmisie celulară"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite aplicației să se conecteze la modulul de transmisie celulară pentru a redirecționa mesajele cu transmisie celulară pe măsură ce le primește. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situațiile de urgență. Aplicațiile rău intenționate pot afecta performanța sau funcționarea dispozitivului dvs. când este primită o transmisie celulară de urgență."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"citește mesajele cu transmisie celulară"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite aplicației să citească mesajele primite prin transmisie celulară de dispozitivul dvs. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situațiile de urgență. Aplicațiile rău intenționate pot afecta performanța sau funcționarea dispozitivului dvs. când este primită o transmisie celulară de urgență."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"citire feeduri abonat"</string>
@@ -662,8 +660,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permite aplicației să citească și să scrie configurația Nu deranja."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"porniți folosirea permisiunii de vizualizare"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite proprietarului să pornească folosirea permisiunii pentru o aplicație. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ținta comenzii rapide de accesibilitate"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite unei aplicații să definească ținta comenzii rapide de accesibilitate."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Să seteze reguli pentru parolă"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Stabiliți lungimea și tipul de caractere permise pentru parolele și codurile PIN de blocare a ecranului."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Să monitorizeze încercările de deblocare a ecranului"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 655cf1b..6390b95 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Приложение сможет получать и обрабатывать SMS. Это значит, что оно сможет отслеживать и удалять отправленные на ваше устройство сообщения, не показывая их."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"Прием MMS-сообщений"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Приложение сможет получать и обрабатывать MMS. Это значит, что оно сможет отслеживать и удалять отправленные на ваше устройство сообщения, не показывая их."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Пересылка сообщений для оповещения населения"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Приложение сможет выполнить привязку к модулю оповещения населения, чтобы пересылать сообщения широковещательных SMS-служб сразу после их получения. В некоторых странах эти сообщения используются для информирования об экстренных ситуациях. Вредоносное ПО может помешать работе устройства, на которое поступают такие сообщения."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"Читать сообщения массовой рассылки"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Приложение получит доступ к сообщениям широковещательных SMS-служб, которые в некоторых странах используются для информирования населения об экстренных ситуациях. Вредоносные программы могут помешать работе устройства, на которое поступают такие сообщения."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"Просмотр фидов пользователя"</string>
@@ -386,7 +384,7 @@
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Приложение сможет постоянно хранить свои компоненты в памяти. Это может уменьшить объем памяти, доступный другим приложениям, и замедлить работу устройства."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="47072473951071734">"Приложение сможет постоянно хранить свои компоненты в памяти. Это может уменьшить объем памяти, доступный другим приложениям, и замедлить работу устройства Android TV."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Приложение сможет постоянно хранить свои компоненты в памяти. Это может уменьшить объем памяти, доступный другим приложениям, и замедлить работу устройства."</string>
-    <string name="permlab_foregroundService" msgid="3310786367649133115">"запускать активные сервисы"</string>
+    <string name="permlab_foregroundService" msgid="3310786367649133115">"Запуск активных сервисов"</string>
     <string name="permdesc_foregroundService" msgid="6471634326171344622">"Разрешить приложению использовать активные сервисы."</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"Вычисление объема памяти приложений"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Приложение сможет получать сведения о размере кода, данных и кеша."</string>
@@ -522,7 +520,7 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Приложение получит доступ к сведениям об уровне сложности блокировки экрана (высокий, средний, низкий или отсутствует), в том числе о типе блокировки и длине пароля. Кроме того, оно сможет предлагать пользователям повысить уровень сложности блокировки. Эти рекомендации необязательны. Обратите внимание, что пароль не хранится в виде открытого текста и недоступен приложению."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"Использование биометрического оборудования"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Приложение сможет использовать биометрическое оборудование для аутентификации"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"управление сканером отпечатков"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"управление сканером отпечатков пальцев"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Приложение сможет добавлять и удалять шаблоны отпечатков пальцев."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Использование сканера отпечатков"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Приложение сможет использовать сканер отпечатков пальцев для аутентификации."</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Открывает приложению доступ к настройкам режима \"Не беспокоить\" и позволяет изменять их."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"Просмотр данных об используемых разрешениях"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Приложение получит доступ к данным об используемых разрешениях. Это разрешение не требуется обычным приложениям."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"Цель быстрого включения"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Приложение сможет определять цель быстрого включения."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Настройка правил для паролей"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Контролировать длину и символы при вводе пароля и PIN-кода."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Отслеживание попыток разблокировать экран"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 5fc6b53..fc69d0e 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS පණිවිඩ ලැබීමට සහ ක්‍රියාත්මක කිරීමට යෙදුමට අවසර දෙන්න. මෙහි තේරුම යෙදුමට ඔබගේ උපාංගයට ලැබෙන පණිවිඩ අධීක්ෂණය කිරීමට හැකිවීම වන අතර, ඒවා ඔබට නොපෙන්වා මකා දැමීමටද හැකි වීමයි."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"පෙළ පණිවුඩ ලබාගන්න (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS පණිවිඩ සොයා ලබාගැනීමට සහ ක්‍රියාත්මක කිරීමට යෙදුමට අවසර දෙන්න. යෙදුම නිරීක්ෂණය කරනු ලබන අතර ඔබට ලැබුන පණිවිඩ පෙන්වීමෙන් තොරවම මකා දැමිය හැකි බව මෙමඟින් අදහස් කරයි."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"සෙල් විකාශන පණිවිඩ යොමු කිරීම"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"සෙල් විකාශන පණිවිඩ ලැබුණු විට ඒවා යොමු කිරීම සඳහා සෙල් විකාශන මොඩියුලයට බැඳීමට යෙදුමට ඉඩ දෙයි. හදිසි අවස්ථා පිළිබඳව ඔබට අනතුරු ඇඟවීම සඳහා සෙල් විකාශන ඇඟවීම් සමහර ස්ථානවල ලබා දෙනු ලැබේ. හදිසි සෙල් විකාශනයක් ලැබෙන අවස්ථාවකදී, අනිෂ්ට යෙදුම්වලින් ඔබගේ උපාංග කාර්ය සාධනයට හෝ මෙහෙයුමට බාධා සිදු විය හැකිය."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"සෙල් ප්‍රචාරණ පණිවිඩ කියවීම"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ඔබගේ උපාංගයට ලැබුණු සෙල් විකාශන පණිවිඩ කියවීමට යෙදුමට අවසර දෙන්න. ඔබට හදිසි අවස්ථාවන් පිළිබඳ අනතුරු ඇඟවීමට සෙල් විකාශන පණිවිඩ ඇතැම් ස්ථානවල සිට යවනු ලබයි. හදිසි සෙල් විකාශන ලැබෙන අවස්ථාවකදී, අනිෂ්ට යෙදුම් මඟින් ඔබගේ උපාංගයට කාර්ය සාධනයට හෝ ක්‍රියකරණයට බාධා සිදුවිය හැක."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"දායක වූ සංග්‍රහ කියවීම"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"බාධා නොකරන්න වින්‍යාස කිරීම කියවීමට සහ ලිවීමට යෙදුමට ඉඩ දෙයි."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"අවසර භාවිතය බැලීමට ආරම්භ කරන්න"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"තබා සිටින්නාට යෙදුමක් සඳහා අවසර භාවිතය ආරම්භ කිරීමට ඉඩ දෙයි. සාමාන්‍ය යෙදුම් සඳහා කිසි විටෙක අවශ්‍ය නොවිය යුතු ය."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ප්‍රවේශ්‍යතා කෙටිමං ඉලක්කය"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ප්‍රවේශ්‍යතා කෙටිමං ඉලක්කය නිර්වචනය කිරීමට යෙදුමකට ඉඩ දෙන්න."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"මුරපද නීති සකස් කිරීම"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"තිර අගුලු මුරපද සහ PIN තුළ ඉඩ දෙන දිග සහ අනුලකුණු පාලනය කිරීම."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"තිරය අගුළු ඇරීමේ උත්සාහයන් නිරීක්ෂණය කරන්න"</string>
@@ -1589,7 +1585,7 @@
     <string name="expires_on" msgid="3676242949915959821">"කල් ඉකුත් වන්නේ:"</string>
     <string name="serial_number" msgid="758814067660862493">"අනුක්‍රමාංකය:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"ඇඟිලි සලකුණු:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ඇඟිලිසලකුණ:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ඇඟිලි සලකුණ:"</string>
     <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ඇඟිලි සලකුණ:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"සියල්ල බලන්න"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"ක්‍රියාකාරකම තෝරන්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index ce17331..59e8b5e 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -330,7 +330,7 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ovládajte umiestnenie a úroveň priblíženia obrazovky."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Gestá"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Je možné použiť klepnutie, prejdenie, stiahnutie prstami a ďalšie gestá."</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestá odtlačkom prstu"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestá odtlačkom prsta"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Dokáže zaznamenať gestá na senzore odtlačkov prstov zariadenia."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"zakázanie alebo zmeny stavového riadka"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Umožňuje aplikácii vypnúť stavový riadok alebo pridať a odstrániť systémové ikony."</string>
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Umožňuje aplikácii prijímať a spracovávať správy SMS. Znamená to, že aplikácia môže sledovať správy odoslané na vaše zariadenie alebo ich odstrániť bez toho, aby sa vám zobrazili."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"prijímať textové správy (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Umožňuje aplikácii prijímať a spracovávať správy MMS. Znamená to, že aplikácia môže sledovať správy odoslané na vaše zariadenie alebo ich odstrániť bez toho, aby sa vám zobrazili."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Preposielanie správ informačných služieb"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Umožňuje aplikácii spojiť sa s modulom správ informačných služieb s cieľom preposielať prichádzajúce správy informačných služieb. Správy informačných služieb sa doručujú na určitých miestach a upozorňujú na tiesňové situácie. Škodlivé aplikácie môžu pri prijatí správy informačnej služby narušiť výkonnosť alebo prevádzku vášho zariadenia."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"čítať správy informačných služieb"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Umožňuje aplikácii čítať správy informačných služieb prijaté vaším zariadením. Správy informačných služieb sa doručujú na určitých miestach a upozorňujú na tiesňové situácie. Škodlivé aplikácie môžu pri prijatí správy informačnej služby narušiť výkonnosť alebo prevádzku vášho zariadenia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čítať odoberané informačné kanály"</string>
@@ -542,17 +540,17 @@
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Nie je nastavený PIN, vzor ani heslo"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Podarilo sa rozpoznať iba časť odtlačku prsta. Skúste to znova."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Odtlačok prsta sa nepodarilo spracovať. Skúste to znova."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Snímač odtlačkov je špinavý. Vyčistite ho a skúste to znova."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Snímač odtlačkov prstov je špinavý. Vyčistite ho a skúste to znova."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Pohli ste prstom príliš rýchlo. Skúste to znova."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Pohli ste prstom príliš pomaly. Skúste to znova."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Odtlačok bol overený"</string>
+    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Odtlačok prsta bol overený"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Tvár bola overená"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Tvár bola overená, stlačte tlačidlo potvrdenia"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardvér na snímanie odtlačku prsta nie je k dispozícii"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Odtlačok prsta nie je možné uložiť. Odstráňte existujúci odtlačok."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit rozpoznania odtlačku vypršal. Skúste to znova."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit rozpoznania odtlačku prsta vypršal. Skúste to znova."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Overenie odtlačku prsta zrušil používateľ."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Príliš veľa pokusov. Skúste to znova neskôr."</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Umožňuje aplikácii čítať a zapisovať konfiguráciu režimu bez vyrušení."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"spustenie používania povolenia na zobrazenie"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Umožňuje držiteľovi spustiť používanie povolenia aplikáciou. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cieľ skratky dostupnosti"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Umožňuje aplikácii definovať cieľ skratky dostupnosti."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastaviť pravidlá pre heslo"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Nastavte dĺžku hesiel na odomknutie obrazovky aj kódov PIN a v nich používané znaky."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Sledovanie pokusov o odomknutie obrazovky"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index ec0863f..c49d5ff 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Aplikaciji omogoča prejemanje in obdelavo SMS-ov. S tem lahko aplikacija nadzoruje ali izbriše sporočila, poslana v napravo, ne da bi vam jih pokazala."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"prejemanje sporočil (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Aplikaciji omogoča prejemanje in obdelavo MMS-ov. S tem lahko aplikacija nadzoruje ali izbriše sporočila, poslana v napravo, ne da bi vam jih pokazala."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Posredovanje sporočil oddaj v celici"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Aplikaciji omogoča povezovanje z modulom za oddaje v celici, da posreduje sporočila oddaj v celici, takoj ko jih prejme. Na nekaterih lokacijah so opozorila oddaj v celici dostavljena, da vas opozorijo na izredne razmere. Zlonamerne aplikacije lahko vplivajo na delovanje naprave, ko prejme sporočilo oddaje v celici."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"branje sporočil oddaje v celici"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Omogoča aplikaciji branje sporočil oddaje v celici, ki jih prejme naprava. Opozorila oddaje v celici so dostavljena na nekaterih lokacijah, da vas opozorijo na izredne razmere. Zlonamerne aplikacije lahko vplivajo na delovanje naprave, ko dobi sporočilo oddaje v celici."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"branje naročenih virov"</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Aplikaciji omogoča branje in pisanje konfiguracije načina »ne moti«."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"začetek uporabe dovoljenja za ogledovanje"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Imetniku omogoča začetek uporabe dovoljenj za aplikacijo. Nikoli ni potrebno za navadne aplikacije."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cilj bližnjice funkcije za ljudi s posebnimi potrebami"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Aplikaciji dovoljuje, da določi cilj bližnjice funkcije za ljudi s posebnimi potrebami."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavitev pravil za geslo"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih in kodah PIN za odklepanje zaslona."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Nadzor nad poskusi odklepanja zaslona"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 95359cc..045c7d5 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Lejon aplikacionin të marrë dhe përpunojë mesazhe SMS. Kjo do të thotë se aplikacioni mund të monitorojë ose fshijë mesazhe të dërguara në pajisjen tënde, pa t\'i treguar ato."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"prano mesazhe në tekst (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Lejon aplikacionin të marrë dhe përpunojë mesazhe MMS. Kjo do të thotë se aplikacioni mund të monitorojë ose fshijë mesazhe të dërguara në pajisjen tënde, pa t\'i treguar ato."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Transmeto mesazhet e transmetimit celular"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Lejon që aplikacioni të lidhet me modulin e transmetimit celular për t\'i transferuar mesazhet e transmetimit celular menjëherë kur merren. Sinjalizimet e transmetimit celular dërgohen në disa vendndodhje për të të paralajmëruar për situata urgjente. Aplikacionet keqdashëse mund të ndërhyjnë në cilësinë e funksionimit ose në veprimin e pajisjes sate kur merret një transmetim celular urgjent."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lexo mesazhet e transmetimit të qelizës"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Lejon aplikacionin të lexojë mesazhet e transmetimit të qelizës, të marra nga pajisja jote. Alarmet e transmetimit të qelizës dërgohen në disa vendndodhje për të të paralajmëruar në situata urgjente. Aplikacionet keqdashëse mund të ndërhyjnë në veprimtarinë ose operacionin e pajisjes tënde kur merret një transmetim urgjent i qelizës."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lexo informacione të abonuara"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Lejon aplikacionin të lexojë dhe shkruajë konfigurimin e \"Mos shqetëso\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"nis përdorimin e lejes për shikimin"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Lejon që mbajtësi të nisë përdorimin e lejeve për një aplikacion. Nuk duhet të nevojitet asnjëherë për aplikacionet normale."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"objektivi i shkurtores së qasshmërisë"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Lejon që një aplikacion të përcaktojë objektivin e shkurtores së qasshmërisë."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Cakto rregullat e fjalëkalimit"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrollo gjatësinë dhe karakteret e lejuara në fjalëkalimet dhe kodet PIN të kyçjes së ekranit."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitoro tentativat e shkyçjes së ekranit"</string>
@@ -1195,7 +1191,7 @@
     <string name="unsupported_display_size_show" msgid="7969129195360353041">"Shfaq gjithmonë"</string>
     <string name="unsupported_compile_sdk_message" msgid="4253168368781441759">"<xliff:g id="APP_NAME">%1$s</xliff:g> është ndërtuar për një version të papërputhshëm të sistemit operativ Android dhe mund të shfaqë sjellje të papritura. Mund të ofrohet një version i përditësuar i aplikacionit."</string>
     <string name="unsupported_compile_sdk_show" msgid="2681877855260970231">"Shfaq gjithnjë"</string>
-    <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"Kliko për përditësim"</string>
+    <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"Kontrollo për përditësim"</string>
     <string name="smv_application" msgid="3307209192155442829">"Aplikacioni <xliff:g id="APPLICATION">%1$s</xliff:g> (procesi <xliff:g id="PROCESS">%2$s</xliff:g>) ka shkelur politikën e tij të vetë-imponuar \"Modaliteti i ashpër\" (StrictMode)."</string>
     <string name="smv_process" msgid="5120397012047462446">"Procesi <xliff:g id="PROCESS">%1$s</xliff:g> ka shkelur politikën e tij të vetë-imponuar \"Modaliteti i rreptë\" (StrictMode)"</string>
     <string name="android_upgrading_title" product="default" msgid="7513829952443484438">"Telefoni po përditësohet…"</string>
@@ -1915,7 +1911,7 @@
     <string name="work_mode_off_message" msgid="5130856710614337649">"Aplikacionet e punës, njoftimet, të dhënat e tua dhe funksionet e tjera të profilit të punës do të aktivizohen"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivizo"</string>
     <string name="deprecated_target_sdk_message" msgid="1449696506742572767">"Ky aplikacion është ndërtuar për një version më të vjetër të Android dhe mund të mos funksionojë mirë. Provo të kontrollosh për përditësime ose kontakto me zhvilluesin."</string>
-    <string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Kliko për përditësim"</string>
+    <string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Kontrollo për përditësim"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Ke mesazhe të reja"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Hap aplikacionin SMS për ta parë"</string>
     <string name="profile_encrypted_title" msgid="4260432497586829134">"Disa funksione mund të jenë të kufizuara"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 39ad5f4..0d8acc6 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -347,10 +347,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Дозвољава апликацији да прима и обрађује SMS поруке. То значи да апликација може да надгледа или брише поруке које се шаљу уређају, а да вам их не прикаже."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"пријем текстуалних порука (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Дозвољава апликацији да прима и обрађује MMS поруке. То значи да апликација може да надгледа или брише поруке које се шаљу уређају, а да вам их не прикаже."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Прослеђивање порука за мобилне уређаје на локалитету"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Дозвољава апликацији да се везује за модул порука за мобилне уређаје на локалитету да би прослеђивала поруке за мобилне уређаје на локалитету онако како су примљене. Обавештења порука за мобилне уређаје на локалитету се на неким локацијама примају као упозорења на хитне случајеве. Злонамерне апликације могу да утичу на учинак или ометају рад уређаја када се прими порука о хитном случају за мобилне уређаје на локалитету."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"читање порука инфо сервиса"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Омогућава апликацији да чита поруке инфо сервиса које уређај прима. Упозорења инфо сервиса се на неким локацијама примају као упозорења на хитне случајеве. Злонамерне апликације могу да утичу на учинак или ометају функционисање уређаја када се прими порука инфо сервиса о хитном случају."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"читање пријављених фидова"</string>
@@ -662,8 +660,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Дозвољава апликацији да чита и уписује конфигурацију подешавања Не узнемиравај."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"почетак коришћења дозволе за преглед"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Дозвољава власнику да започне коришћење дозволе за апликацију. Никада не би требало да буде потребна за уобичајене апликације."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"циљ пречице за приступачност"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Дозвољава апликацији да дефинише циљ пречице за приступачност."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Подешавање правила за лозинку"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Контролише дужину и знакове дозвољене у лозинкама и PIN-овима за закључавање екрана."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Надгледајте покушаје откључавања екрана"</string>
@@ -1610,8 +1606,8 @@
     <string name="expires_on" msgid="3676242949915959821">"Истиче:"</string>
     <string name="serial_number" msgid="758814067660862493">"Серијски број:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Дигитални отисци:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 дигитални отисак:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 дигитални отисак:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 отисак прста:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 отисак прста:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Прикажи све"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Избор активности"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Дели са"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 061d7b7..dba5ebb 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Tillåter att appen tar emot och hanterar SMS. Detta innebär att appen kan övervaka eller ta bort meddelanden som skickats till enheten utan att visa dem för dig."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ta emot textmeddelanden (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Tillåter att appen tar emot och hanterar MMS-meddelanden. Detta innebär att appen kan övervaka eller ta bort meddelanden som skickats till enheten utan att visa dem för dig."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Vidarebefordra massutskick via sms"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Tillåter att appen binds till cellsändningsmodulen så att massutskick via sms kan vidarebefordras vid mottagandet. I vissa områden används massutskick via sms för att varna om nödsituationer. Skadliga appar kan påverka enhetens prestanda eller funktioner när ett massutskick via sms tas emot."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"läsa SMS-meddelanden"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Appen tillåts läsa SMS som skickas till din enhet. På vissa platser skickas SMS för att varna för nödsituationer. Skadliga appar kan påverka enhetens prestanda eller funktionalitet när du får ett meddelande om en nödsituation via SMS."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"läsa flöden som du prenumererar på"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Ger appen läs- och skrivbehörighet till konfigurationen för Stör ej."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"börja visa behörighetsanvändningen"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Gör att innehavaren kan öppna behörighetsanvändning för en app. Ska inte behövas för vanliga appar."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"mål för Aktivera tillgänglighet snabbt"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Tillåter att en app kan definiera målet för Aktivera tillgänglighet snabbt."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ange lösenordsregler"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Styr tillåten längd och tillåtna tecken i lösenord och pinkoder för skärmlåset."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Övervaka försök att låsa upp skärmen"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 16df4e3..89e3231 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Inaruhusu programu kupokea na kuchakata ujumbe wa SMS. Hii inamaanisha programu hii inaweza kuchunguza na kufuta ujumbe uliotumwa katika kifaa chako bila ya kukuonyesha."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"pokea ujumbe wa maandishi wa MMS"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Inaruhusu programu kupokea na kuchakata ujumbe medianwai (MMS). Hii inamaanisha uwezo wa kuchunguza na kufuta ujumbe uliotumwa kwa kifaa chako bila ya kukuonyesha."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Sambaza ujumbe wa matangazo ya simu"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Huruhusu programu ipachikwe katika sehemu ya matangazo ya simu ili isambaze ujumbe wa matangazo ya simu unapopokewa. Arifa za matangazo ya simu huwasilishwa katika maeneo mengine ili kukuonya juu ya hali za dharura. Huenda programu hasidi zikatatiza utendaji au shughuli ya kifaa chako matangazo ya simu ya dharura yanapopokewa."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"soma mawasiliano ya matangazo ya simu"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Huruhusu programu kusoma mawasiliano ya matangazo ya simu yaliyoingia kwenye kifaa chako. Arifa za matangazo ya simu huwasilishwa katika maeneo mengine ili kukuonya juu ya hali za dharura. Huenda programu hasidi zikatatiza utendajikazi au shughuli ya kifaa chako wakati matangazo ya simu ya dharura yameingia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"kusoma mipasho kutoka vyanzo unavyofuatilia"</string>
@@ -516,9 +514,9 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Huruhusu programu kupata maelezo kuhusu kiwango cha uchangamano wa kufunga skrini (juu, wastani, chini au hakuna), ambacho huashiria urefu unaowezekana na aina ya kufunga skrini. Programu pia inaweza kumpendekezea mtumiaji asasishe mbinu ya kufunga skrini iwe ya kiwango fulani lakini mtumiaji anaweza kuamua kupuuza na kuendelea. Kumbuka kuwa maelezo ya kufunga skrini hayahifadhiwi kama maandishi, hivyo programu haitambui nenosiri mahususi."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"tumia maunzi ya kibiolojia"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Huruhusu programu itumie maunzi ya kibiolojia katika uthibitishaji"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"dhibiti maunzi ya kitambulisho"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Huruhusu programu kuomba njia za kuongeza na kufuta violezo vya kitambulisho kwa matumizi."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"tumia maunzi ya kitambulisho"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"dhibiti maunzi ya alama ya kidole"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Huruhusu programu kuomba njia za kuongeza na kufuta violezo vya alama ya kidole kwa matumizi."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"tumia maunzi ya alama ya kidole"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Huruhusu programu kutumia maunzi ya kitambulisho kwa uthibitisho"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"kubadilisha mkusanyiko wako wa muziki"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Inaruhusu programu kubadilisha mkusanyiko wako wa muziki."</string>
@@ -534,7 +532,7 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Hayatambuliki"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Imeghairi uthibitishaji"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Hujaweka pin, mchoro au nenosiri"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Kitambuzi kimegundua sehemu ya kitambulisho. Tafadhali jaribu tena."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Kitambuzi kimegundua sehemu ya alama ya kidole. Tafadhali jaribu tena."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Imeshindwa kuchakata alama ya kidole. Tafadhali jaribu tena."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Kitambuzi alama ya kidole ni kichafu. Tafadhali kisafishe na ujaribu tena."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Ulisogeza kidole kwa kasi mno. Tafadhali jaribu tena."</string>
@@ -544,10 +542,10 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Imethibitisha alama ya kidole"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Uso umethibitishwa"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Uso umethibitishwa, tafadhali bonyeza thibitisha"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Maunzi ya kitambulisho hayapatikani."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Kitambulisho hakiwezi kuhifadhiwa. Tafadhali ondoa kitambulisho kilichopo."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Muda wa kitambulisho umekwisha. Jaribu tena."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Utendaji wa kitambulisho imeghairiwa."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Maunzi ya alama ya kidole hayapatikani."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Alama ya kidole haiwezi kuhifadhiwa. Tafadhali ondoa alama ya kidole iliyopo."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Muda wa kuweka alama ya kidole umekwisha. Jaribu tena."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Mchakato wa alama ya kidole umeghairiwa."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Mtumiaji ameghairi uthibitishaji wa alama ya kidole."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Majaribio mengi mno. Jaribu tena baadaye."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Majaribio mengi mno. Kitambua alama ya kidole kimezimwa."</string>
@@ -557,7 +555,7 @@
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Kidole cha <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Aikoni ya kitambulisho"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Aikoni ya alama ya kidole"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"dhibiti maunzi ya kufungua kwa uso"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"Huruhusu programu iombe njia za kuongeza na kufuta violezo vya uso vitakavyotumiwa."</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"tumia maunzi ya kufungua kwa uso"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Inaruhusu programu kusoma na kuandika usanidi wa kipengee cha Usinisumbue."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"anzisha kipengele cha kuona matumizi ya ruhusa"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Huruhusu kishikiliaji kuanzisha matumizi ya ruhusa ya programu. Haipaswi kuhitajika kwa ajili ya programu za kawaida."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"kulenga njia ya mkato ya ufikivu"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Huruhusu programu kubainisha ulengaji wa njia ya mkato ya ufikivu."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Kuweka kanuni za nenosiri"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Dhibiti urefu na maandishi yanayokubalika katika nenosiri la kufunga skrini na PIN."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Kuhesabu mara ambazo skrini inajaribu kufunguliwa"</string>
@@ -1555,7 +1551,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Chaguo zaidi"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Hifadhi ya ndani inayoshirikiwa"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Hifadhi ya ndani ya pamoja"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Kadi ya SD"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"Kadi ya SD iliyotengenezwa na <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"Hifadhi ya USB"</string>
@@ -1587,8 +1583,8 @@
     <string name="expires_on" msgid="3676242949915959821">"Inaisha muda mnamo:"</string>
     <string name="serial_number" msgid="758814067660862493">"Nambari ya ufuatiliaji:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Alazama za Vidole:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"Alama ya  kidole ya SHA-256:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"Alama ya kidole ya  SHA-1:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Kitambulisho dijitali cha SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Kitambulisho dijitali cha  SHA-1:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Angalia zote"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Chagua shughuli"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Shiriki na"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 3b80a43..0ed1421 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS செய்திகளைப் பெற, செயற்படுத்தப் ஆப்ஸை அனுமதிக்கிறது. இதற்கு அர்த்தம் உங்கள் சாதனத்திற்கு அனுப்பப்படும் செய்திகளை உங்களுக்குக் காட்டாமல் கண்காணிப்பதற்கு அல்லது நீக்குவதற்கு ஆப்ஸால் முடியும் என்பதாகும்."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"உரைச் செய்திகளை (MMS) பெறுதல்"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS செய்திகளைப் பெற, செயற்படுத்தப் ஆப்ஸை அனுமதிக்கிறது. இதற்கு அர்த்தம் உங்கள் சாதனத்திற்கு அனுப்பப்படும் செய்திகளை உங்களுக்குக் காட்டாமல் கண்காணிக்கவோ, நீக்கவோ ஆப்ஸால் முடியும் என்பதாகும்."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"செல் பிராட்காஸ்ட் மெசேஜ்களை முன்னனுப்பு"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"செல் பிராட்காஸ்ட் மெசேஜ்களைப் பெறும்போதெல்லாம் அவற்றை முன்னனுப்பும் பொருட்டு, ஆப்ஸை செல் பிராட்காஸ்ட் மாடியூலோடு இணைக்கும். சில இடங்களில் அவசர சூழ்நிலைகளின் போது உங்களை எச்சரிக்க செல் பிராட்காஸ்ட் விழிப்பூட்டல்கள் அனுப்பப்படும். அவசரநிலை செல் பிராட்காஸ்ட்டைப் பெறும்போது, தீங்கிழைக்கும் ஆப்ஸ் உங்கள் சாதனத்தின் செயல்திறனுக்கோ செயல்பாட்டிற்கோ இடையூறு விளைவிக்கக்கூடும்."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"செல் அலைபரப்புச் செய்திகளைப் படித்தல்"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"உங்கள் சாதனத்தில் பெறப்படும் செல் அலைபரப்புச் செய்திகளைப் படிப்பதற்குப் ஆப்ஸை அனுமதிக்கிறது. அவசரநிலை சூழ்நிலைகளை உங்களுக்கு எச்சரிக்கைச் செய்வதற்கு சில இடங்களில் செல் அலைபரப்பு விழிப்பூட்டல்கள் வழங்கப்படும். அவசரநிலை மொபைல் அலைபரப்புப் பெறப்படும்போது உங்கள் சாதனத்தின் செயல்திறன் அல்லது செயல்பாட்டுடன் தீங்கிழைக்கும் ஆப்ஸ் அதைத் தடுக்கலாம்."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"குழுசேர்ந்த ஊட்டங்களைப் படித்தல்"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"தொந்தரவு செய்ய வேண்டாம் உள்ளமைவைப் படிக்கவும் எழுதவும், ஆப்ஸை அனுமதிக்கிறது."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"அனுமதி உபயோகத்தை அணுகுதல்"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ஆப்ஸிற்கான அனுமதி உபயோகத்தை ஹோல்டருக்கு வழங்கும். இயல்பான ஆப்ஸிற்கு இது எப்போதுமே தேவைப்படாது."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"அணுகலம்ச ஷார்ட்கட் இலக்கு"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"அணுகலம்ச ஷார்ட்கட் இலக்கை விளக்க ஆப்ஸை அனுமதிக்கும்."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"கடவுச்சொல் விதிகளை அமைக்கவும்"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"திரைப் பூட்டின் கடவுச்சொற்கள் மற்றும் பின்களில் அனுமதிக்கப்படும் நீளத்தையும் எழுத்துக்குறிகளையும் கட்டுப்படுத்தும்."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"திரையைத் திறப்பதற்கான முயற்சிகளைக் கண்காணி"</string>
@@ -1352,7 +1348,7 @@
     <string name="no_permissions" msgid="7283357728219338112">"அனுமதிகள் தேவையில்லை"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"இதனால் நீங்கள் கட்டணம் செலுத்த வேண்டியிருக்கலாம்"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"சரி"</string>
-    <string name="usb_charging_notification_title" msgid="1595122345358177163">"USB மூலமாக இந்தச் சாதனம் சார்ஜ் ஆகிறது"</string>
+    <string name="usb_charging_notification_title" msgid="1595122345358177163">"USBயில் சாதனம் சார்ஜ் ஆகிறது"</string>
     <string name="usb_supplying_notification_title" msgid="4631045789893086181">"USB மூலமாக இணைக்கப்பட்ட சாதனம் சார்ஜ் ஆகிறது"</string>
     <string name="usb_mtp_notification_title" msgid="4238227258391151029">"USB மூலமாக ஃபைல் பரிமாற்றம் ஆன் செய்யப்பட்டது"</string>
     <string name="usb_ptp_notification_title" msgid="5425857879922006878">"USB மூலமாக PTP பயன்முறை ஆன் செய்யப்பட்டது"</string>
@@ -1364,7 +1360,7 @@
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"அனலாக் ஆடியோ துணைக்கருவி கண்டறியப்பட்டது"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"இணைத்துள்ள சாதனமானது இந்த மொபைலுடன் இணங்கவில்லை. மேலும் அறிய, தட்டவும்."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB பிழைதிருத்தம் இணைக்கப்பட்டது"</string>
-    <string name="adb_active_notification_message" msgid="7463062450474107752">"USB பிழைதிருத்தத்தை ஆஃப் செய்ய, தட்டவும்"</string>
+    <string name="adb_active_notification_message" msgid="7463062450474107752">"USB பிழைதிருத்தத்தை ஆஃப் செய்ய தட்டவும்"</string>
     <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB பிழைதிருத்தத்தை முடக்க, தேர்ந்தெடுக்கவும்."</string>
     <string name="test_harness_mode_notification_title" msgid="2216359742631914387">"\'தன்னியக்க சோதனைப்\' பயன்முறை இயக்கப்பட்டது"</string>
     <string name="test_harness_mode_notification_message" msgid="1343197173054407119">"’தன்னியக்க சோதனைப்\' பயன்முறையை முடக்க ஆரம்பநிலைக்கு மீட்டமைக்கவும்."</string>
@@ -1588,8 +1584,8 @@
     <string name="expires_on" msgid="3676242949915959821">"காலாவதியாவது:"</string>
     <string name="serial_number" msgid="758814067660862493">"வரிசை எண்:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"கைரேகைகள்:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 கைரேகை:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 கைரேகை:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ஃபிங்கர்பிரிண்ட்:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ஃபிங்கர்பிரிண்ட்:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"எல்லாம் காட்டு"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"செயல்பாட்டைத் தேர்வுசெய்க"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"இதனுடன் பகிர்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 37e0590..72b83c4 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. యాప్ మీ డివైజ్‌కు పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"వచన సందేశాలను (MMS) స్వీకరించడం"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. యాప్ మీ డివైజ్‌కు పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"సెల్ ప్రసార సందేశాలను ఫార్వర్డ్ చేయడం"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"సెల్ ప్రసార సందేశాలను అందుకుంటే, వాటిని ఫార్వర్డ్ చేసే విధంగా సెల్ ప్రసార మాడ్యూల్‌కు కట్టుబడి ఉండటానికి యాప్‌ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం అందుకున్నప్పుడు హానికరమైన యాప్‌లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"సెల్ ప్రసార సందేశాలను చదవడం"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార సందేశాలను చదవడానికి యాప్‌ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం స్వీకరించినప్పుడు హానికరమైన యాప్‌లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"చందా చేయబడిన ఫీడ్‌లను చదవడం"</string>
@@ -517,9 +515,9 @@
     <string name="permlab_useBiometric" msgid="8837753668509919318">"బయోమెట్రిక్ హార్డ్‌వేర్‌ని ఉపయోగించు"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"ప్రమాణీకరణ కోసం బయోమెట్రిక్ హార్డ్‌వేర్‌ను ఉపయోగించడానికి యాప్‌ని అనుమతిస్తుంది"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"వేలిముద్ర హార్డ్‌వేర్‌ని నిర్వహించడానికి అనుమతి"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"వినియోగం కోసం వేలిముద్ర టెంప్లేట్‌లను జోడించే మరియు తొలగించే పద్ధతులను అమలు చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"వినియోగం కోసం వేలిముద్ర టెంప్లేట్‌లను జోడించే, తొలగించే పద్ధతులను అమలు చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"వేలిముద్ర హార్డ్‌వేర్‌ని ఉపయోగించడానికి అనుమతి"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ప్రామాణీకరణ కోసం వేలిముద్ర హార్డ్‌వేర్‌ను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ప్రామాణీకరణ కోసం వేలిముద్ర హార్డ్‌వేర్‌ను ఉపయోగించడానికి యాప్‌ను అనుమతిస్తుంది"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"మీ సంగీత సేకరణను సవరించండి"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"మీ సంగీత సేకరణని సవరించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"మీ వీడియో సేకరణను సవరించండి"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"అంతరాయం కలిగించవద్దు ఎంపిక కాన్ఫిగరేషన్ చదవడానికి మరియు వ్రాయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"వీక్షణ అనుమతి వినియోగాన్ని ప్రారంభించండి"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"యాప్‌నకు అనుమతి వినియోగాన్ని ప్రారంభించడానికి హోల్డర్‌‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ ఇటువంటి అనుమతి అవసరం ఉండదు."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"యాక్సెసిబిలిటీ షార్ట్‌కట్ లక్ష్యం"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"యాక్సెసిబిలిటీ షార్ట్‌కట్ లక్ష్యాన్ని నిర్వచించడానికి యాప్‌ను అనుమతించండి."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"పాస్‌వర్డ్ నియమాలను సెట్ చేయండి"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"స్క్రీన్ లాక్ పాస్‌వర్డ్‌లు మరియు PINల్లో అనుమతించబడిన పొడవు మరియు అక్షరాలను నియంత్రిస్తుంది."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"స్క్రీన్ అన్‌లాక్ ప్రయత్నాలను పర్యవేక్షించండి"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 482288e..caaa32d 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ SMS ซึ่งหมายความว่าแอปพลิเคชันจะสามารถตรวจสอบหรือลบข้อความที่ส่งมายังอุปกรณ์ของคุณได้โดยไม่ต้องแสดงให้คุณเห็น"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"รับข้อความ (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ MMS ซึ่งหมายความว่าแอปพลิเคชันจะสามารถตรวจสอบหรือลบข้อความที่ส่งมายังอุปกรณ์ของคุณได้โดยไม่ต้องแสดงให้คุณเห็น"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"ส่งต่อข้อความจากการส่งข้อมูลเตือนภัยทางมือถือ (CB)"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"อนุญาตให้แอปเชื่อมโยงกับโมดูลการส่งข้อมูลเตือนภัยทางมือถือ (CB) เพื่อส่งต่อข้อความจากการส่งข้อมูลเตือนภัยทางมือถือ (CB) ทันทีที่ได้รับ ระบบจะส่งการแจ้งเตือนจากการส่งข้อมูลเตือนภัยทางมือถือ (CB) ในบางตำแหน่งเพื่อแจ้งเตือนคุณเกี่ยวกับสถานการณ์ฉุกเฉิน แอปที่เป็นอันตรายอาจรบกวนประสิทธิภาพหรือการทำงานของอุปกรณ์เมื่อได้รับการส่งข้อมูลเตือนภัยทางมือถือ (CB) ในกรณีฉุกเฉิน"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"อ่านข้อความที่ได้รับจากสถานีมือถือ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"อนุญาตให้แอปอ่านข้อความจากสถานีมือถือที่อุปกรณ์ได้รับ การแจ้งเตือนทางมือถือมีให้บริการในบางพื้นที่ โดยจะแจ้งเตือนคุณเกี่ยวกับสถานการณ์ฉุกเฉิน แอปที่เป็นอันตรายอาจเข้าแทรกแซงการทำงานของอุปกรณ์เมื่อได้รับข้อความแจ้งเตือนฉุกเฉิน"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"อ่านฟีดข้อมูลที่สมัครไว้"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"อนุญาตให้แอปอ่านและเขียนการกำหนดค่าโหมดห้ามรบกวน"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"เริ่มการใช้สิทธิ์การดู"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"อนุญาตให้เจ้าของเริ่มการใช้สิทธิ์ของแอป ไม่จำเป็นสำหรับแอปทั่วไป"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"เป้าหมายทางลัดการช่วยเหลือพิเศษ"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"อนุญาตให้แอปกำหนดเป้าหมายทางลัดการช่วยเหลือพิเศษ"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ตั้งค่ากฎรหัสผ่าน"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"ควบคุมความยาวและอักขระที่สามารถใช้ในรหัสผ่านของการล็อกหน้าจอและ PIN"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
@@ -1555,7 +1551,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"ตัวเลือกเพิ่มเติม"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"ที่จัดเก็บข้อมูลที่ใช้ร่วมกันภายใน"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"พื้นที่จัดเก็บข้อมูลที่ใช้ร่วมกันภายใน"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"การ์ด SD"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"การ์ด SD ของ <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"ไดรฟ์ USB"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index f2db658..01cf28f 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Pinapayagan ang app na tumanggap at magproseso ng mga mensaheng SMS. Nangangahulugan ito na maaaring sumubaybay o magtanggal ang app ng mga mensaheng ipinapadala sa iyong device nang hindi ipinapakita ang mga ito sa iyo."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"tumanggap ng mga text message (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Pinapayagan ang app na tumanggap at magproseso ng mga mensaheng MMS. Nangangahulugan ito na maaaring sumubaybay o magtanggal ang app ng mga mensaheng ipinapadala sa iyong device nang hindi ipinapakita ang mga ito sa iyo."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Magpasa ng mga mensahe ng cell broadcast"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Nagbibigay-daan sa app na mag-bind sa module ng cell broadcast para makapagpasa ng mga mensahe ng cell broadcast pagkatanggap sa mga ito. Inihahatid ang mga alerto ng cell broadcast sa ilang lokasyon para balaan ka tungkol sa mga emergency na sitwasyon. Posibleng makasagabal ang mga nakakahamak na app sa performance o pagpapatakbo ng iyong device kapag nakatanggap ito ng emergency na cell broadcast."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"basahin ang mga mensahe ng cell broadcast"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Binibigyang-daan ang app na magbasa ng mga mensahe ng cell broadcast na natanggap ng iyong device. Inihahatid ang mga alerto ng cell broadcast sa ilang lokasyon upang balaan ka tungkol sa mga emergency na sitwasyon. Maaaring makaabala ang nakakahamak na apps sa performance o pagpapatakbo ng iyong device kapag nakatanggap ng emergency na cell broadcast."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"magbasa ng mga na-subscribe na feed"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Nagbibigay-daan sa app na basahin at isulat ang configuration ng Huwag Istorbohin."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"simulan ang paggamit sa pahintulot sa pagtingin"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Binibigyang-daan ang may hawak na simulan ang paggamit ng pahintulot para sa isang app. Hindi dapat kailanganin kailanman para sa mga normal na app."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"Target ng shortcut sa pagiging accessible"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Nagbibigay-daan sa isang app na tukuyin ang target ng shortcut sa pagiging accessible."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Magtakda ng mga panuntunan sa password"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolin ang haba at ang mga character na pinapayagan sa mga password at PIN sa screen lock."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string>
@@ -1351,7 +1347,7 @@
     <string name="no_permissions" msgid="7283357728219338112">"Walang mga kinakailangang pahintulot"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"maaari itong magdulot ng gastos sa iyo"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="usb_charging_notification_title" msgid="1595122345358177163">"China-charge ang device na ito sa pamamagitan ng USB"</string>
+    <string name="usb_charging_notification_title" msgid="1595122345358177163">"China-charge ang device sa USB"</string>
     <string name="usb_supplying_notification_title" msgid="4631045789893086181">"China-charge ang nakakonektang device sa pamamagitan ng USB"</string>
     <string name="usb_mtp_notification_title" msgid="4238227258391151029">"Na-on ang paglipat ng USB file"</string>
     <string name="usb_ptp_notification_title" msgid="5425857879922006878">"Na-on ang PTP sa pamamagitan ng USB"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index cf3fbfc..d3e9d93 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Uygulamaya SMS iletilerini alma ve işleme izni verir. Bu izin, uygulamanın cihazınıza gönderilen iletileri takip edip size göstermeden silebileceği anlamına gelir."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"kısa mesajları (MMS) al"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Uygulamaya MMS iletilerini alma ve işleme izni verir. Bu izin, uygulamanın cihazınıza gönderilen iletileri takip edip size göstermeden silebileceği anlamına gelir."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Hücre yayını mesajlarını yönlendirme"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Uygulamanın hücre yayını mesajları geldiğinde bunları yönlendirmek için hücre yayını modülüne bağlanmasına izin verir. Hücre yayını uyarıları bazı konumlarda acil durumlar hakkında sizi uyarmak için kullanılır. Zararlı uygulamalar acil durum hücre yayını alındığında cihazınızın performansını ve çalışmasını olumsuz etkileyebilir."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"hücre yayını mesajlarını oku"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Uygulamaya, cihazınız tarafından alınan hücre yayını mesajlarını okuma izni verir. Hücre yayını uyarıları bazı yerlerde acil durumlar konusunda sizi uyarmak için gönderilir. Kötü amaçlı uygulamalar acil hücre yayını alındığında cihazınızın performansına ya da çalışmasına engel olabilir."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"abone olunan yayınları okuma"</string>
@@ -550,7 +548,7 @@
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Parmak izi işlemi iptal edildi."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Parmak izi işlemi kullanıcı tarafından iptal edildi."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Çok fazla deneme yapıldı. Daha sonra tekrar deneyin."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Çok fazla deneme yapıldı. Parmak izi sensörü devre dışı bıraıldı."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Çok fazla deneme yapıldı. Parmak izi sensörü devre dışı bırakıldı."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tekrar deneyin."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Parmak izi kaydedilmedi."</string>
     <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Bu cihazda parmak izi sensörü yok."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Uygulamaya, Rahatsız Etmeyin yapılandırmasını okuma ve yazma izni verir."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"izin kullanımı görüntülemeye başlama"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"İzin sahibinin bir uygulama için izin kullanımı başlatmasına olanak tanır. Normal uygulamalar için hiçbir zaman kullanılmamalıdır."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"erişilebilirlik kısayolu hedefi"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Uygulamaların erişilebilirlik kısayolu hedefi tanımlamasına izin verir."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Şifre kuralları ayarla"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ekran kilidini açma şifrelerinde ve PIN\'lerde izin verilen uzunluğu ve karakterleri denetleyin."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Ekran kilidini açma denemelerini izle"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 0ac716d..88350a2 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Дозволяє програмі отримувати й обробляти SMS-повідомлення. Це означає, що програма може відстежувати чи видаляти повідомлення, надіслані на ваш пристрій, навіть не показуючи їх вам."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"отримувати текстові повідомлення (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Дозволяє програмі отримувати й обробляти MMS-повідомлення. Це означає, що програма може відстежувати чи видаляти повідомлення, надіслані на ваш пристрій, навіть не показуючи їх вам."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Переадресувати повідомлення Cell Broadcast"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Дозволяє додатку зв\'язуватися з модулем Cell Broadcast, щоб переадресувати відповідні вхідні повідомлення. У деяких місцеположеннях сповіщення Cell Broadcast надсилаються для попередження про надзвичайні ситуації. Після повідомлення Cell Broadcast шкідливі додатки можуть перешкоджати роботі вашого пристрою."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"читати широкомовні повідомлення мережі"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Дозволяє програмі читати широкомовні повідомлення мережі, отримані пристроєм. Широкомовні сповіщення мережі надсилаються в деяких країнах для попередження про надзвичайні ситуації. Шкідливі програми можуть втручатися у швидкодію чи роботу пристрою під час отримання широкомовного повідомлення мережі про надзвичайну ситуацію."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"читати підписані канали"</string>
@@ -522,10 +520,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Дозволяє додатку визначати рівень складності способу блокування екрана (високий, середній, низький або нульовий). Враховуються кількість символів і тип блокування. Додаток також може пропонувати вибрати складніший тип блокування екрана, але це не обов’язково робити. Примітка: оскільки пароль зашифровано, додаток його не знає."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"використовувати біометричне апаратне забезпечення"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Додаток може використовувати біометричне апаратне забезпечення для автентифікації"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"керувати апаратним забезпеченням для цифрових відбитків"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Увімкнути в додатку функції для додавання й видалення шаблонів цифрових відбитків."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"використання сканера цифрових відбитків"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозволити додатку використовувати апаратне забезпечення для автентифікації"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"керувати сканером відбитків пальців"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Увімкнути в додатку функції для додавання й видалення шаблонів відбитків пальців."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"використання сканера відбитків пальців"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозволити додатку використовувати сканер відбитків пальців для автентифікації"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"змінювати колекцію музики"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Додаток зможе змінювати вашу колекцію музики."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"змінювати колекцію відео"</string>
@@ -540,20 +538,20 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Не розпізнано"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Автентифікацію скасовано"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Не вказано PIN-код, ключ або пароль"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Відбиток розпізнано частково. Повторіть спробу."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не вдалось обробити відбиток. Повторіть спробу."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Датчик відбитків забруднився. Очистьте його та повторіть спробу."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Відбиток пальця розпізнано частково. Повторіть спробу."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не вдалось обробити відбиток пальця. Повторіть спробу."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Датчик відбитків пальців забруднився. Очистьте його та повторіть спробу."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Ви забрали палець надто швидко. Повторіть спробу."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Ви провели пальцем надто повільно. Повторіть спробу."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Відбиток автентифіковано"</string>
+    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Відбиток пальця автентифіковано"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Обличчя автентифіковано"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Обличчя автентифіковано. Натисніть \"Підтвердити\""</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Апаратне забезпечення для сканування відбитка недоступне."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Не вдалося зберегти відбиток. Видаліть наявний відбиток."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час очікування відбитка минув. Повторіть спробу."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Дію з відбитком скасовано."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Сканер відбитків пальців недоступний."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Не вдалося зберегти відбиток пальця. Видаліть наявний відбиток."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час очікування відбитка пальця минув. Повторіть спробу."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Дію з відбитком пальця скасовано."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Користувач скасував дію з відбитком пальця."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Забагато спроб. Спробуйте пізніше."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Забагато спроб. Сканер відбитків пальців вимкнено."</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Додаток зможе переглядати та змінювати конфігурацію режиму \"Не турбувати\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"перегляньте дані про використання дозволів"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Власник зможе використовувати дозволи для цього додатка. Цей дозвіл не потрібен для звичайних додатків."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"потрібні засоби спеціальних можливостей"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Дає додатку змогу визначати потрібні засоби спеціальних можливостей."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Устан. правила пароля"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Укажіть максимальну довжину та кількість символів для паролів розблокування екрана та PIN-кодів."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Відстежувати спроби розблокування екрана"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 43ecaf6..e5015ea 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"‏ایپ کو SMS پیغامات حاصل اور ان پر کارروائی کرنے کی اجازت دیتا ہے۔ اس کا مطلب ہے کہ ایپ آپ کے آلے پر مرسلہ پیغامات آپ کو دکھائے بغیر ان پر نگاہ رکھ یا انہیں حذف کرسکتی ہے۔"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"‏متنی پیغامات (MMS) حاصل کریں"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"‏ایپ کو MMS پیغامات حاصل اور ان پر کارروائی کرنے کی اجازت دیتا ہے۔ اس کا مطلب ہے کہ ایپ آپ کے آلے پر مرسلہ پیغامات آپ کو دکھائے بغیر ان پر نگاہ رکھ یا انہیں حذف کرسکتی ہے۔"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"سیل کے نشریاتی پیغامات فارورڈ کریں"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"سیل کی نشریاتی پیغامات کے موصول ہوتے ہی فارورڈ کرنے کے لیے ایپ کو سیل کے نشریاتی ماڈیول میں پابندی لگانے کی اجازت دیں۔ سیل کی نشریاتی الرٹس آپ کو ہنگامی حالات سے مطلع کرنے کیلئے کچھ مقامات میں مہیا کی جاتی ہیں۔ نقصان دہ ایپس کوئی ہنگامی سیل براڈ کاسٹ موصول ہونے پر آپ کے آلے کی کارکردگی یا عمل میں مداخلت کر سکتی ہیں۔"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"سیل کے نشریاتی پیغامات پڑھیں"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ایپ کو آپ کے آلے کو موصولہ سیل کے نشریاتی پیغامات پڑھنے کی اجازت دیتا ہے۔ سیل کی نشریاتی الرٹس آپ کو ہنگامی حالات سے مطلع کرنے کیلئے کچھ مقامات میں مہیا کی جاتی ہیں۔ نقصان دہ ایپس کوئی ہنگامی سیل کا نشریہ موصول ہونے پر آپ کے آلے کی کارکردگی یا عمل میں خلل ڈال سکتی ہیں۔"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"سبسکرائب کردہ فیڈز پڑھیں"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"ایپ کو ڈسٹرب نہ کریں کنفیگریشن لکھنے اور پڑھنے کے قابل کرتا ہے۔"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"اجازت کی استعمال کا ملاحظہ شروع کریں"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"حامل کو ایپ کی اجازت کے استعمال کو شروع کرنے کی اجازت دیتا ہے۔ عام ایپس کے لیے کبھی بھی درکار نہیں ہونا چاہیے۔"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ایکسیسبیلٹی شارٹ کٹ ہدف"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ایپ کو ایکسیسبیلٹی شارٹ کٹ ہدف کی وضاحت کرنے کے ليے اجازتیں۔"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"پاس ورڈ کے اصول سیٹ کریں"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"‏اسکرین لاک پاس ورڈز اور PINs میں اجازت یافتہ لمبائی اور حروف کو کنٹرول کریں۔"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"اسکرین غیر مقفل کرنے کی کوششیں مانیٹر کریں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 5ebda207..8899747 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Ilovaga SMS xabarlarini qabul qilish va va ularni qayta ishlash uchun ruxsat beradi. Bu sizga yuborilgan xabarlarni ilova sizga ko‘rsatmasdan kuzatishi va o‘chirishi mumkinligini bildiradi."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"MMS xabarlarni olish"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Ilovaga MMS xabarlarini qabul qilish va ularni qayta ishlash uchun ruxsat beradi. Bu sizga yuborilgan xabarlarni ilova sizga ko‘rsatmasdan kuzatishi va o‘chirishi mumkinligini bildiradi."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Aholini ogohlantirish xabarlarini uzatish"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Qabul qilingan aholini ogohlantirish xabarlarini shu holicha uzatish uchun ilovani aholini ogohlantirish moduliga bogʻlash imkonini beradi. Ilovaga ayrim mamlakatlarda aholini favqulodda vaziyatlarda ogohlantirish uchun yuboriladigan tarqatma xabarlarni oʻqish uchun ruxsat beradi. Zararli dasturlar bunday xabarlar kelayotgan qurilmaning ishlashiga xalaqit qilishi mumkin."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"uyali tarmoq operatori xabarlarini o‘qish"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Ilovaga qurilmangiz tomonidan qabul qilingan uyali tarmoq operatori xabarlarini o‘qish uchun ruxsat beradi. Uyali tarmoq operatorining ogohlantiruvchi xabarlari ba’zi manzillarga favqulodda holatlar haqida ogohlantirish uchun jo‘natiladi. Zararli ilovalar uyali tarmoq orqali favqulodda xabar qabul qilinganda qurilmangizning ish faoliyati yoki amallariga xalaqit qilishi mumkin"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"obunalarni o‘qish"</string>
@@ -536,7 +534,7 @@
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"PIN kod, grafik kalit yoki parol sozlanmagan"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Barmoq izi qisman aniqlandi. Qayta urinib ko‘ring."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Barmoq izi aniqlanmadi. Qaytadan urining."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Skanerni tozalab, keyin qaytadan urining."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Barmoq izi skanerini tozalab, keyin qaytadan urining."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Barmoq juda tez harakatlandi. Qaytadan urining."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Barmoq juda sekin harakatlandi. Qayta urinib ko‘ring."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"“Bezovta qilinmasin” rejimi sozlamalarini ko‘rish va o‘zgartirish."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"foydalaniladigan ruxsatlar axborotini ochish"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Ilova foydalanadigan ruxsatlar axborotini ishga tushirishga ruxsat beradi. Oddiy ilovalar uchun talab qilinmaydi."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"tezkor yoqish maqsadi"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Ilova tezkor yoqish maqsadini aniqlay oladi."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Parol qoidalarini o‘rnatish"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ekran qulfi paroli va PIN kodlari uchun qo‘yiladigan talablarni (belgilar soni va uzunligi) nazorat qiladi."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Ekranni qulfdan chiqarishga urinishlarni nazorat qilish"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index a34585b..fc8994e 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Cho phép ứng dụng nhận và xử lý tin nhắn SMS. Điều này có nghĩa là ứng dụng có thể theo dõi hoặc xóa tin nhắn được gửi đến thiết bị của bạn mà không hiển thị chúng cho bạn."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"nhận tin nhắn văn bản (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Cho phép ứng dụng nhận và xử lý tin nhắn MMS. Điều này có nghĩa là ứng dụng có thể theo dõi hoặc xóa tin nhắn được gửi đến thiết bị của bạn mà không hiển thị chúng cho bạn."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Chuyển tiếp tin nhắn truyền phát trên di động"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Cho phép ứng dụng liên kết với mô-đun truyền phát trên di động để chuyển tiếp tin nhắn truyền phát trên di động ngay khi nhận được. Ở một số vị trí, thông báo truyền phát trên di động sẽ được gửi nhằm cảnh báo cho bạn về các tình huống khẩn cấp. Các ứng dụng độc hại có thể ảnh hưởng đến hiệu suất hoặc hoạt động của thiết bị khi nhận được tin nhắn truyền phát trên di động lúc khẩn cấp."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"đọc tin nhắn quảng bá"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Cho phép ứng dụng đọc tin nhắn quảng bá mà thiết bị của bạn nhận được. Tin nhắn quảng bá cảnh báo được gửi ở một số địa điểm nhằm cảnh báo cho bạn về các tình huống khẩn cấp. Các ứng dụng độc hại có thể gây ảnh hưởng đến hiệu suất hoặc hoạt động của thiết bị của bạn khi nhận được tin nhắn quảng bá khẩn cấp."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"đọc nguồn cấp dữ liệu đã đăng ký"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Cho phép ứng dụng đọc và ghi cấu hình Không làm phiền."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"cấp quyền xem"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Cho phép chủ sở hữu cấp quyền cho một ứng dụng. Các ứng dụng thông thường sẽ không bao giờ cần quyền này."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"đích đến của phím tắt hỗ trợ tiếp cận"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Cho phép ứng dụng xác định đích đến của phím tắt hỗ trợ tiếp cận."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Đặt quy tắc mật khẩu"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kiểm soát độ dài và ký tự được phép trong mật khẩu khóa màn hình và mã PIN."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Giám sát những lần thử mở khóa màn hình"</string>
@@ -737,7 +733,7 @@
   </string-array>
     <string name="phoneTypeCustom" msgid="1644738059053355820">"Tùy chỉnh"</string>
     <string name="phoneTypeHome" msgid="2570923463033985887">"Nhà riêng"</string>
-    <string name="phoneTypeMobile" msgid="6501463557754751037">"Di Động"</string>
+    <string name="phoneTypeMobile" msgid="6501463557754751037">"Di động"</string>
     <string name="phoneTypeWork" msgid="8863939667059911633">"Cơ quan"</string>
     <string name="phoneTypeFaxWork" msgid="3517792160008890912">"Số fax cơ quan"</string>
     <string name="phoneTypeFaxHome" msgid="2067265972322971467">"Số fax nhà riêng"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 64e0a1b..56d8153 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"允许该应用接收和处理短信。这就意味着,该应用可能会监视发送到您设备的短信,或删除发送到您设备的短信而不向您显示。"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"接收讯息(彩信)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"允许该应用接收和处理彩信。这就意味着,该应用可能会监视发送到您设备的彩信,或删除发送到您设备的彩信而不向您显示。"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"转发小区广播消息"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"允许应用绑定到小区广播模块,以便及时转发收到的小区广播消息。小区广播消息是在某些地区发送的、用于发布紧急情况警告的提醒信息。恶意应用可能会在您的设备收到紧急小区广播时干扰设备的性能或操作。"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"读取小区广播消息"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"允许应用读取您的设备收到的小区广播消息。小区广播消息是在某些地区发送的、用于发布紧急情况警告的提醒信息。恶意应用可能会在您收到小区紧急广播时干扰您设备的性能或操作。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"读取订阅的供稿"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"允许此应用读取和写入“勿扰”模式配置。"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"授权使用“查看权限”"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"允许该应用开始查看应用的权限使用情况(普通应用绝不需要此权限)。"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"无障碍功能快捷方式目标"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"允许应用定义无障碍功能快捷方式目标。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"控制锁屏密码和 PIN 码所允许的长度和字符。"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"监控屏幕解锁尝试次数"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 67a7dbb..c8360aa 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"允許應用程式接收和處理短訊。這表示應用程式可監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"接收短訊 (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"允許應用程式接收和處理 MMS 訊息。這表示應用程式可監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"轉寄區域廣播訊息"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"允許應用程式繫結至區域廣播模組,以在收到區域廣播訊息時轉寄訊息。在某些地點,系統會發出區域廣播通知,提示您有緊急狀況發生。惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"讀取區域廣播訊息"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"允許應用程式讀取您裝置接收的區域廣播訊息。某些地點會發出區域廣播警報,警告您發生緊急狀況。惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的性能或運作。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"讀取訂閱的資訊提供"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"允許應用程式讀取和寫入「請勿騷擾」設定。"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"開始查看權限使用情況"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"允許應用程式開始查看應用程式的權限使用情況 (一般應用程式並不需要)。"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"無障礙功能捷徑目標位置"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"允許應用程式定義無障礙功能捷徑目標位置。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"控制螢幕鎖定密碼和 PIN 所允許的長度和字元。"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"監控螢幕解鎖嘗試次數"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 923a23f..23b68e1 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"允許應用程式接收和處理簡訊。這項設定可讓應用程式監控傳送至你裝置的訊息,或在你閱讀訊息前擅自刪除訊息。"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"接收簡訊 (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"允許應用程式接收和處理多媒體訊息。這項設定可讓應用程式監控傳送至你裝置的訊息,或在你閱讀訊息前擅自刪除訊息。"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"轉送區域廣播訊息"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"允許應用程式繫結至區域廣播模組,以便轉送收到的區域廣播訊息。某些地點會發出區域廣播警示,警告你有緊急狀況發生。請注意,惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"讀取區域廣播訊息"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"允許應用程式讀取你裝置收到的區域廣播訊息。某些地點會發出區域廣播警示,警告你有緊急狀況發生。請注意,惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"讀取訂閱資訊提供"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"允許應用程式讀取及寫入「零打擾」設定。"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"啟動檢視權限用途"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"允許應用程式開始使用其他應用程式 (一般應用程式並不需要)。"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"指定無障礙捷徑目標"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"允許應用程式定義指定的無障礙捷徑目標。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"管理螢幕鎖定密碼和 PIN 碼支援的字元和長度上限。"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"監控螢幕解鎖嘗試次數"</string>
@@ -1588,7 +1584,7 @@
     <string name="serial_number" msgid="758814067660862493">"序號:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"指紋"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 指紋"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 指紋"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 指紋:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"全部顯示"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"選擇活動"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"分享活動"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 04091ff..dac7c10 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Ivumela uhlelo lokusebenza ukuthola nokucubungula imilayezo ye-SMS. Loku kuchaza ukuthi uhlelo lokusebenza lungangamela noma lesuse imilayezo ethunyelwe kudivayisi yakho ngaphandle kokukubonisa yona."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"thola imiyalezo ebhaliwe (i-MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Ivumela uhlelo lokusebenza ukuthola nokucubungula imilayezo ye-MMS. Loku kuchaza ukuthi uhlelo lokusebenza lungangamela noma lesuse imilayezo ethunyelwe kudivayisi yakho ngaphandle kokukubonisa yona."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Dlulisela imilayezo yokusakaza kweselula"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Ivumela uhlelo lokusebenza ukuthi luboshezelwe kumojuli yokusakaza kweselula ukuze kudluliselwe imilayezo yokusakaza yeselula njengoba itholwa. Izexwayiso zokusakaza kweselula zilethwa kwezinye izindawo ukuze zikuxwayise ngezimo zesimo esiphuthumayo. Izinhlelo zokusebenza ezinobungozi zingaphazamisa ngokusebenza noma ukusetshenziswa kwedivayisi yakho uma ukusakaza kweselula kwesimo esiphuthumayo kwamukelwa."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"funda imilayezo yokusakaza yeselula"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Ivumela uhlelo lokusebenza ukufunda imilayezo yokusakaza yeselula etholwe idivayisi yakho. Izaziso zokusakaza zeselula zilethwa kwezinye izindawo ukukuxwayisa ngezimo ezisheshayo. Izinhlelo zokusebenza ezingalungile zingaphazamisana nokusebenza noma umsebenzi wedivayisi yakho uma ukusakaza kweselula kwesimo esisheshayo kutholwa."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"funda izifunzo ezikhokhelwayo"</string>
@@ -541,14 +539,14 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Umnwe uhanjiswe kancane kakhulu. Sicela uzame futhi."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Isingxivizo somunwe sigunyaziwe"</string>
+    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Izigxivizo zeminwe zigunyaziwe"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Ubuso bufakazelwe ubuqiniso"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Ukuqinisekiswa kobuso, sicela ucindezele okuthi qinisekisa"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Izingxenyekazi zekhompuyutha zezingxivizo zeminwe azitholakali."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Izingxenyekazi zekhompuyutha zezigxivizo zeminwe azitholakali."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Izigxivizo zeminwe azikwazi ukugcinwa. Sicela ususe izigxivizo zeminwe ezikhona."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Kufinyelelwe isikhathi sokuvala sezigxivizo zeminwe. Zama futhi"</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Ukusebenza kwezingxivizo zeminwe kukhanseliwe."</string>
-    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Umsebenzi wesigxivizo somunwe sikhanselwe umsebenzisi."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Ukusebenza kwezigxivizo zeminwe kukhanseliwe."</string>
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Umsebenzi wezigxivizo zomunwe ukhanselwe umsebenzisi."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Imizamo eminingi kakhulu. Zama futhi emuva kwesikhathi."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Imizamo eminingi kakhulu. Inzwa yezigxivizo zeminwe ikhutshaziwe."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Zama futhi."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Ivumela izinhlelo zokusebenza ukufunda nokubhala ukulungiswa kokuthi Ungaphazamisi."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"qala ukusetshenziswa kokubuka imvume"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Ivumela umphathi ukuthi aqale ukusetshenziswa kwemvume kohlelo lokusebenza. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"impokophelo yesinqamuleli sokufinyeleleka"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Ivumela uhlelo lokusebenza ukuthi luchaze impokophelo yesinqamuleli sokufinyeleleka."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Misa imithetho yephasiwedi"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Lawula ubude nezinhlamvu ezivunyelwe kumaphasiwedi wokukhiya isikrini nama-PIN."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Qapha imizamo yokuvula isikrini sakho"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 14f5d97..acaaeec 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3701,6 +3701,8 @@
             <flag name="flagRequestFingerprintGestures" value="0x00000200" />
             <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK}. -->
             <flag name="flagRequestShortcutWarningDialogSpokenFeedback" value="0x00000400" />
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_HANDLE_SHORTCUT}. -->
+            <flag name="flagHandleShortcut" value="0x00000800" />
         </attr>
         <!-- Component name of an activity that allows the user to modify
              the settings for this service. This setting cannot be changed at runtime. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index a301702..ffcfe43 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -295,6 +295,12 @@
         <!-- Additional flag from base permission type: this permission can be automatically
             granted to the system app predictor -->
         <flag name="appPredictor" value="0x200000" />
+        <!-- Additional flag from base permission type: this permission can be automatically
+            granted to the system telephony apps -->
+        <flag name="telephony" value="0x400000" />
+        <!-- Additional flag from base permission type: this permission can be automatically
+            granted to the system wifi app-->
+        <flag name="wifi" value="0x800000" />
     </attr>
 
     <!-- Flags indicating more context for a permission group. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 3fef7a2d..affb306 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -387,6 +387,12 @@
     </string-array>
 
     <!-- List of regexpressions describing the interface (if any) that represent tetherable
+         Wifi P2P interfaces.  If the device doesn't want to support tethering over Wifi P2p this
+         should be empty.  An example would be "p2p-p2p.*" -->
+    <string-array translatable="false" name="config_tether_wifi_p2p_regexs">
+    </string-array>
+
+    <!-- List of regexpressions describing the interface (if any) that represent tetherable
          WiMAX interfaces.  If the device doesn't want to support tethering over Wifi this
          should be empty.  An example would be "softap.*" -->
     <string-array translatable="false" name="config_tether_wimax_regexs">
@@ -442,7 +448,7 @@
     </string-array>
 
     <!-- Package name for the default CellBroadcastService module [DO NOT TRANSLATE] -->
-    <string name="cellbroadcast_default_package" translatable="false">com.android.cellbroadcastreceiver
+    <string name="cellbroadcast_default_package" translatable="false">com.android.cellbroadcastservice
     </string>
 
     <!-- If the mobile hotspot feature requires provisioning, a package name and class name
@@ -758,6 +764,9 @@
     <!-- Indicates that p2p MAC randomization is supported on this device -->
     <bool translatable="false" name="config_wifi_p2p_mac_randomization_supported">false</bool>
 
+    <!-- Indicates that AP mode MAC randomization is supported on this device -->
+    <bool translatable="false" name="config_wifi_ap_mac_randomization_supported">true</bool>
+
     <!-- flag for activating paranoid MAC randomization on a limited set of SSIDs -->
     <bool translatable="false" name="config_wifi_aggressive_randomization_ssid_whitelist_enabled">false</bool>
 
@@ -3687,6 +3696,21 @@
      -->
     <string name="config_defaultWellbeingPackage" translatable="false"></string>
 
+    <!-- The package name for the system telephony apps.
+         This package must be trusted, as it will be granted with permissions with special telephony
+         protection level. Note, framework by default support multiple telephony apps, each package
+         name is separated by comma.
+         Example: "com.android.phone,com.android.stk,com.android.providers.telephony"
+     -->
+    <string name="config_telephonyPackages" translatable="false">"com.android.phone,com.android.stk,com.android.providers.telephony,com.android.ons"</string>
+
+    <!-- The package name for the default system wifi app.
+         This package must be trusted, as it has the permissions to control wifi
+         connectivity on the device.
+         Example: "com.android.wifi"
+     -->
+    <string name="config_wifiPackage" translatable="false">"com.android.wifi"</string>
+
     <!-- The component name for the default system attention service.
          This service must be trusted, as it can be activated without explicit consent of the user.
          See android.attention.AttentionManagerService.
@@ -4304,11 +4328,11 @@
 
     <!-- Trigger a warning for notifications with RemoteView objects that are larger in bytes than
     this value (default 1MB)-->
-    <integer name="config_notificationWarnRemoteViewSizeBytes">1000000</integer>
+    <integer name="config_notificationWarnRemoteViewSizeBytes">2000000</integer>
 
     <!-- Strip notification RemoteView objects that are larger in bytes than this value (also log)
     (default 2MB) -->
-    <integer name="config_notificationStripRemoteViewSizeBytes">2000000</integer>
+    <integer name="config_notificationStripRemoteViewSizeBytes">5000000</integer>
 
     <!-- Contains a blacklist of apps that should not get pre-installed carrier app permission
          grants, even if the UICC claims that the app should be privileged. See b/138150105 -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c5a0dfc..8dcd282 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1920,6 +1920,7 @@
   <java-symbol type="bool" name="config_tether_upstream_automatic" />
   <java-symbol type="array" name="config_tether_usb_regexs" />
   <java-symbol type="array" name="config_tether_wifi_regexs" />
+  <java-symbol type="array" name="config_tether_wifi_p2p_regexs" />
   <java-symbol type="array" name="config_usbHostBlacklist" />
   <java-symbol type="array" name="config_serialPorts" />
   <java-symbol type="array" name="radioAttributes" />
@@ -1970,6 +1971,7 @@
   <java-symbol type="bool" name="config_wifi_local_only_hotspot_5ghz" />
   <java-symbol type="bool" name="config_wifi_connected_mac_randomization_supported" />
   <java-symbol type="bool" name="config_wifi_p2p_mac_randomization_supported" />
+  <java-symbol type="bool" name="config_wifi_ap_mac_randomization_supported" />
   <java-symbol type="bool" name="config_wifi_aggressive_randomization_ssid_whitelist_enabled" />
   <java-symbol type="bool" name="config_wifi_link_probing_supported" />
   <java-symbol type="bool" name="config_wifi_fast_bss_transition_enabled" />
@@ -3467,6 +3469,8 @@
   <java-symbol type="string" name="config_defaultAutofillService" />
   <java-symbol type="string" name="config_defaultTextClassifierPackage" />
   <java-symbol type="string" name="config_defaultWellbeingPackage" />
+  <java-symbol type="string" name="config_telephonyPackages" />
+  <java-symbol type="string" name="config_wifiPackage" />
   <java-symbol type="string" name="config_defaultContentCaptureService" />
   <java-symbol type="string" name="config_defaultAugmentedAutofillService" />
   <java-symbol type="string" name="config_defaultAppPredictionService" />
diff --git a/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java b/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
index 4ae9494..fb0dd46 100644
--- a/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
+++ b/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
@@ -20,52 +20,44 @@
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
 import static android.app.admin.PasswordMetrics.complexityLevelToMinQuality;
-import static android.app.admin.PasswordMetrics.getActualRequiredQuality;
-import static android.app.admin.PasswordMetrics.getMinimumMetrics;
-import static android.app.admin.PasswordMetrics.getTargetQualityMetrics;
 import static android.app.admin.PasswordMetrics.sanitizeComplexityLevel;
+import static android.app.admin.PasswordMetrics.validatePasswordMetrics;
+
+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_PATTERN;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 
 import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.widget.PasswordValidationError;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
 /** Unit tests for {@link PasswordMetrics}. */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@Presubmit
 public class PasswordMetricsTest {
-
-    @Test
-    public void testIsDefault() {
-        final PasswordMetrics metrics = new PasswordMetrics();
-        assertEquals(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, metrics.quality);
-        assertEquals(0, metrics.length);
-        assertEquals(0, metrics.letters);
-        assertEquals(0, metrics.upperCase);
-        assertEquals(0, metrics.lowerCase);
-        assertEquals(0, metrics.numeric);
-        assertEquals(0, metrics.symbols);
-        assertEquals(0, metrics.nonLetter);
-    }
-
     @Test
     public void testParceling() {
-        final int quality = 0;
+        final int credType = CREDENTIAL_TYPE_PASSWORD;
         final int length = 1;
         final int letters = 2;
         final int upperCase = 3;
@@ -73,20 +65,21 @@
         final int numeric = 5;
         final int symbols = 6;
         final int nonLetter = 7;
+        final int nonNumeric = 8;
+        final int seqLength = 9;
 
         final Parcel parcel = Parcel.obtain();
-        final PasswordMetrics metrics;
+        PasswordMetrics metrics = new PasswordMetrics(credType, length, letters, upperCase,
+                lowerCase, numeric, symbols, nonLetter, nonNumeric, seqLength);
         try {
-            new PasswordMetrics(
-                    quality, length, letters, upperCase, lowerCase, numeric, symbols, nonLetter)
-                    .writeToParcel(parcel, 0);
+            metrics.writeToParcel(parcel, 0);
             parcel.setDataPosition(0);
             metrics = PasswordMetrics.CREATOR.createFromParcel(parcel);
         } finally {
             parcel.recycle();
         }
 
-        assertEquals(quality, metrics.quality);
+        assertEquals(credType, metrics.credType);
         assertEquals(length, metrics.length);
         assertEquals(letters, metrics.letters);
         assertEquals(upperCase, metrics.upperCase);
@@ -94,7 +87,8 @@
         assertEquals(numeric, metrics.numeric);
         assertEquals(symbols, metrics.symbols);
         assertEquals(nonLetter, metrics.nonLetter);
-
+        assertEquals(nonNumeric, metrics.nonNumeric);
+        assertEquals(seqLength, metrics.seqLength);
     }
 
     @Test
@@ -111,23 +105,6 @@
     }
 
     @Test
-    public void testComputeForPassword_quality() {
-        assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC,
-                PasswordMetrics.computeForPassword("a1".getBytes()).quality);
-        assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
-                PasswordMetrics.computeForPassword("a".getBytes()).quality);
-        assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
-                PasswordMetrics.computeForPassword("*~&%$".getBytes()).quality);
-        assertEquals(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX,
-                PasswordMetrics.computeForPassword("1".getBytes()).quality);
-        // contains a long sequence so isn't complex
-        assertEquals(PASSWORD_QUALITY_NUMERIC,
-                PasswordMetrics.computeForPassword("1234".getBytes()).quality);
-        assertEquals(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
-                PasswordMetrics.computeForPassword("".getBytes()).quality);
-    }
-
-    @Test
     public void testMaxLengthSequence() {
         assertEquals(4, PasswordMetrics.maxLengthSequence("1234".getBytes()));
         assertEquals(5, PasswordMetrics.maxLengthSequence("13579".getBytes()));
@@ -142,69 +119,15 @@
     }
 
     @Test
-    public void testEquals() {
-        PasswordMetrics metrics0 = new PasswordMetrics();
-        PasswordMetrics metrics1 = new PasswordMetrics();
-        assertNotEquals(metrics0, null);
-        assertNotEquals(metrics0, new Object());
-        assertEquals(metrics0, metrics0);
-        assertEquals(metrics0, metrics1);
-
-        assertEquals(new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4),
-                new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4));
-
-        assertNotEquals(new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4),
-                new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 5));
-
-        assertNotEquals(new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4),
-                new PasswordMetrics(PASSWORD_QUALITY_COMPLEX, 4));
-
-        metrics0 = PasswordMetrics.computeForPassword("1234abcd,./".getBytes());
-        metrics1 = PasswordMetrics.computeForPassword("1234abcd,./".getBytes());
-        assertEquals(metrics0, metrics1);
-        metrics1.letters++;
-        assertNotEquals(metrics0, metrics1);
-        metrics1.letters--;
-        metrics1.upperCase++;
-        assertNotEquals(metrics0, metrics1);
-        metrics1.upperCase--;
-        metrics1.lowerCase++;
-        assertNotEquals(metrics0, metrics1);
-        metrics1.lowerCase--;
-        metrics1.numeric++;
-        assertNotEquals(metrics0, metrics1);
-        metrics1.numeric--;
-        metrics1.symbols++;
-        assertNotEquals(metrics0, metrics1);
-        metrics1.symbols--;
-        metrics1.nonLetter++;
-        assertNotEquals(metrics0, metrics1);
-        metrics1.nonLetter--;
-        assertEquals(metrics0, metrics1);
-
-
-    }
-
-    @Test
-    public void testConstructQuality() {
-        PasswordMetrics expected = new PasswordMetrics();
-        expected.quality = PASSWORD_QUALITY_COMPLEX;
-
-        PasswordMetrics actual = new PasswordMetrics(PASSWORD_QUALITY_COMPLEX);
-
-        assertEquals(expected, actual);
-    }
-
-    @Test
     public void testDetermineComplexity_none() {
         assertEquals(PASSWORD_COMPLEXITY_NONE,
-                PasswordMetrics.computeForPassword("".getBytes()).determineComplexity());
+                new PasswordMetrics(CREDENTIAL_TYPE_NONE).determineComplexity());
     }
 
     @Test
     public void testDetermineComplexity_lowSomething() {
         assertEquals(PASSWORD_COMPLEXITY_LOW,
-                new PasswordMetrics(PASSWORD_QUALITY_SOMETHING).determineComplexity());
+                new PasswordMetrics(CREDENTIAL_TYPE_PATTERN).determineComplexity());
     }
 
     @Test
@@ -324,122 +247,84 @@
     }
 
     @Test
-    public void testGetTargetQualityMetrics_noneComplexityReturnsDefaultMetrics() {
-        PasswordMetrics metrics =
-                getTargetQualityMetrics(PASSWORD_COMPLEXITY_NONE, PASSWORD_QUALITY_ALPHANUMERIC);
-
-        assertTrue(metrics.isDefault());
+    public void testMerge_single() {
+        PasswordMetrics metrics = new PasswordMetrics(CREDENTIAL_TYPE_PASSWORD);
+        assertEquals(CREDENTIAL_TYPE_PASSWORD,
+                PasswordMetrics.merge(Collections.singletonList(metrics)).credType);
     }
 
     @Test
-    public void testGetTargetQualityMetrics_qualityNotAllowedReturnsMinQualityMetrics() {
-        PasswordMetrics metrics =
-                getTargetQualityMetrics(PASSWORD_COMPLEXITY_MEDIUM, PASSWORD_QUALITY_NUMERIC);
-
-        assertEquals(PASSWORD_QUALITY_NUMERIC_COMPLEX, metrics.quality);
-        assertEquals(/* expected= */ 4, metrics.length);
+    public void testMerge_credentialTypes() {
+        PasswordMetrics none = new PasswordMetrics(CREDENTIAL_TYPE_NONE);
+        PasswordMetrics pattern = new PasswordMetrics(CREDENTIAL_TYPE_PATTERN);
+        PasswordMetrics password = new PasswordMetrics(CREDENTIAL_TYPE_PASSWORD);
+        assertEquals(CREDENTIAL_TYPE_PATTERN,
+                PasswordMetrics.merge(Arrays.asList(new PasswordMetrics[]{none, pattern}))
+                        .credType);
+        assertEquals(CREDENTIAL_TYPE_PASSWORD,
+                PasswordMetrics.merge(Arrays.asList(new PasswordMetrics[]{none, password}))
+                        .credType);
+        assertEquals(CREDENTIAL_TYPE_PASSWORD,
+                PasswordMetrics.merge(Arrays.asList(new PasswordMetrics[]{password, pattern}))
+                        .credType);
     }
 
     @Test
-    public void testGetTargetQualityMetrics_highComplexityNumericComplex() {
-        PasswordMetrics metrics = getTargetQualityMetrics(
-                PASSWORD_COMPLEXITY_HIGH, PASSWORD_QUALITY_NUMERIC_COMPLEX);
+    public void testValidatePasswordMetrics_credentialTypes() {
+        PasswordMetrics none = new PasswordMetrics(CREDENTIAL_TYPE_NONE);
+        PasswordMetrics pattern = new PasswordMetrics(CREDENTIAL_TYPE_PATTERN);
+        PasswordMetrics password = new PasswordMetrics(CREDENTIAL_TYPE_PASSWORD);
 
-        assertEquals(PASSWORD_QUALITY_NUMERIC_COMPLEX, metrics.quality);
-        assertEquals(/* expected= */ 8, metrics.length);
+        // To pass minimal length check.
+        password.length = 4;
+
+        // No errors expected, credential is of stronger or equal type.
+        assertValidationErrors(
+                validatePasswordMetrics(none, PASSWORD_COMPLEXITY_NONE, false, none));
+        assertValidationErrors(
+                validatePasswordMetrics(none, PASSWORD_COMPLEXITY_NONE, false, pattern));
+        assertValidationErrors(
+                validatePasswordMetrics(none, PASSWORD_COMPLEXITY_NONE, false, password));
+        assertValidationErrors(
+                validatePasswordMetrics(pattern, PASSWORD_COMPLEXITY_NONE, false, pattern));
+        assertValidationErrors(
+                validatePasswordMetrics(pattern, PASSWORD_COMPLEXITY_NONE, false, password));
+        assertValidationErrors(
+                validatePasswordMetrics(password, PASSWORD_COMPLEXITY_NONE, false, password));
+
+        // Now actual credential type is weaker than required:
+        assertValidationErrors(
+                validatePasswordMetrics(pattern, PASSWORD_COMPLEXITY_NONE, false, none),
+                PasswordValidationError.WEAK_CREDENTIAL_TYPE, 0);
+        assertValidationErrors(
+                validatePasswordMetrics(password, PASSWORD_COMPLEXITY_NONE, false, none),
+                PasswordValidationError.WEAK_CREDENTIAL_TYPE, 0);
+        assertValidationErrors(
+                validatePasswordMetrics(password, PASSWORD_COMPLEXITY_NONE, false, pattern),
+                PasswordValidationError.WEAK_CREDENTIAL_TYPE, 0);
     }
 
-    @Test
-    public void testGetTargetQualityMetrics_mediumComplexityAlphabetic() {
-        PasswordMetrics metrics = getTargetQualityMetrics(
-                PASSWORD_COMPLEXITY_MEDIUM, PASSWORD_QUALITY_ALPHABETIC);
+    /**
+     * @param expected sequense of validation error codes followed by requirement values, must have
+     *                even number of elements. Empty means no errors.
+     */
+    private void assertValidationErrors(
+            List<PasswordValidationError> actualErrors, int... expected) {
+        assertEquals("Test programming error: content shoud have even number of elements",
+                0, expected.length % 2);
+        assertEquals("wrong number of validation errors", expected.length / 2, actualErrors.size());
+        HashMap<Integer, Integer> errorMap = new HashMap<>();
+        for (PasswordValidationError error : actualErrors) {
+            errorMap.put(error.errorCode, error.requirement);
+        }
 
-        assertEquals(PASSWORD_QUALITY_ALPHABETIC, metrics.quality);
-        assertEquals(/* expected= */ 4, metrics.length);
-    }
-
-    @Test
-    public void testGetTargetQualityMetrics_lowComplexityAlphanumeric() {
-        PasswordMetrics metrics = getTargetQualityMetrics(
-                PASSWORD_COMPLEXITY_MEDIUM, PASSWORD_QUALITY_ALPHANUMERIC);
-
-        assertEquals(PASSWORD_QUALITY_ALPHANUMERIC, metrics.quality);
-        assertEquals(/* expected= */ 4, metrics.length);
-    }
-
-    @Test
-    public void testGetActualRequiredQuality_nonComplex() {
-        int actual = getActualRequiredQuality(
-                PASSWORD_QUALITY_NUMERIC_COMPLEX,
-                /* requiresNumeric= */ false,
-                /* requiresLettersOrSymbols= */ false);
-
-        assertEquals(PASSWORD_QUALITY_NUMERIC_COMPLEX, actual);
-    }
-
-    @Test
-    public void testGetActualRequiredQuality_complexRequiresNone() {
-        int actual = getActualRequiredQuality(
-                PASSWORD_QUALITY_COMPLEX,
-                /* requiresNumeric= */ false,
-                /* requiresLettersOrSymbols= */ false);
-
-        assertEquals(PASSWORD_QUALITY_UNSPECIFIED, actual);
-    }
-
-    @Test
-    public void testGetActualRequiredQuality_complexRequiresNumeric() {
-        int actual = getActualRequiredQuality(
-                PASSWORD_QUALITY_COMPLEX,
-                /* requiresNumeric= */ true,
-                /* requiresLettersOrSymbols= */ false);
-
-        assertEquals(PASSWORD_QUALITY_NUMERIC, actual);
-    }
-
-    @Test
-    public void testGetActualRequiredQuality_complexRequiresLetters() {
-        int actual = getActualRequiredQuality(
-                PASSWORD_QUALITY_COMPLEX,
-                /* requiresNumeric= */ false,
-                /* requiresLettersOrSymbols= */ true);
-
-        assertEquals(PASSWORD_QUALITY_ALPHABETIC, actual);
-    }
-
-    @Test
-    public void testGetActualRequiredQuality_complexRequiresNumericAndLetters() {
-        int actual = getActualRequiredQuality(
-                PASSWORD_QUALITY_COMPLEX,
-                /* requiresNumeric= */ true,
-                /* requiresLettersOrSymbols= */ true);
-
-        assertEquals(PASSWORD_QUALITY_ALPHANUMERIC, actual);
-    }
-
-    @Test
-    public void testGetMinimumMetrics_userInputStricter() {
-        PasswordMetrics metrics = getMinimumMetrics(
-                PASSWORD_COMPLEXITY_HIGH,
-                PASSWORD_QUALITY_ALPHANUMERIC,
-                PASSWORD_QUALITY_NUMERIC,
-                /* requiresNumeric= */ false,
-                /* requiresLettersOrSymbols= */ false);
-
-        assertEquals(PASSWORD_QUALITY_ALPHANUMERIC, metrics.quality);
-        assertEquals(/* expected= */ 6, metrics.length);
-    }
-
-    @Test
-    public void testGetMinimumMetrics_actualRequiredQualityStricter() {
-        PasswordMetrics metrics = getMinimumMetrics(
-                PASSWORD_COMPLEXITY_HIGH,
-                PASSWORD_QUALITY_UNSPECIFIED,
-                PASSWORD_QUALITY_NUMERIC,
-                /* requiresNumeric= */ false,
-                /* requiresLettersOrSymbols= */ false);
-
-        assertEquals(PASSWORD_QUALITY_NUMERIC_COMPLEX, metrics.quality);
-        assertEquals(/* expected= */ 8, metrics.length);
+        for (int i = 0; i < expected.length / 2; i++) {
+            final int expectedError = expected[i * 2];
+            final int expectedRequirement = expected[i * 2 + 1];
+            assertTrue("error expected but not reported: " + expectedError,
+                    errorMap.containsKey(expectedError));
+            assertEquals("unexpected requirement for error: " + expectedError,
+                    Integer.valueOf(expectedRequirement), errorMap.get(expectedError));
+        }
     }
 }
diff --git a/core/tests/coretests/src/android/app/admin/PasswordPolicyTest.java b/core/tests/coretests/src/android/app/admin/PasswordPolicyTest.java
new file mode 100644
index 0000000..e951054
--- /dev/null
+++ b/core/tests/coretests/src/android/app/admin/PasswordPolicyTest.java
@@ -0,0 +1,196 @@
+/*
+ * 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.server.devicepolicy;
+
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+
+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_PATTERN;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.admin.PasswordMetrics;
+import android.app.admin.PasswordPolicy;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class PasswordPolicyTest {
+
+    public static final int TEST_VALUE = 10;
+
+    @Test
+    public void testGetMinMetrics_unspecified() {
+        PasswordPolicy policy = testPolicy(PASSWORD_QUALITY_UNSPECIFIED);
+        PasswordMetrics minMetrics = policy.getMinMetrics();
+        assertEquals(CREDENTIAL_TYPE_NONE, minMetrics.credType);
+        assertEquals(0, minMetrics.length);
+        assertEquals(0, minMetrics.numeric);
+    }
+
+    @Test
+    public void testGetMinMetrics_something() {
+        PasswordPolicy policy = testPolicy(PASSWORD_QUALITY_SOMETHING);
+        PasswordMetrics minMetrics = policy.getMinMetrics();
+        assertEquals(CREDENTIAL_TYPE_PATTERN, minMetrics.credType);
+        assertEquals(0, minMetrics.length);
+        assertEquals(0, minMetrics.numeric);
+    }
+
+    @Test
+    public void testGetMinMetrics_biometricWeak() {
+        PasswordPolicy policy = testPolicy(PASSWORD_QUALITY_BIOMETRIC_WEAK);
+        PasswordMetrics minMetrics = policy.getMinMetrics();
+        assertEquals(CREDENTIAL_TYPE_PATTERN, minMetrics.credType);
+        assertEquals(0, minMetrics.length);
+        assertEquals(0, minMetrics.numeric);
+    }
+
+    @Test
+    public void testGetMinMetrics_numeric() {
+        PasswordPolicy policy = testPolicy(PASSWORD_QUALITY_NUMERIC);
+        PasswordMetrics minMetrics = policy.getMinMetrics();
+        assertEquals(CREDENTIAL_TYPE_PASSWORD, minMetrics.credType);
+        assertEquals(TEST_VALUE, minMetrics.length);
+        assertEquals(0, minMetrics.numeric); // numeric can doesn't really require digits.
+        assertEquals(0, minMetrics.letters);
+        assertEquals(0, minMetrics.lowerCase);
+        assertEquals(0, minMetrics.upperCase);
+        assertEquals(0, minMetrics.symbols);
+        assertEquals(0, minMetrics.nonLetter);
+        assertEquals(0, minMetrics.nonNumeric);
+        assertEquals(Integer.MAX_VALUE, minMetrics.seqLength);
+    }
+
+    @Test
+    public void testGetMinMetrics_numericDefaultLength() {
+        PasswordPolicy policy = testPolicy(PASSWORD_QUALITY_NUMERIC);
+        policy.length = 0; // reset to default
+        PasswordMetrics minMetrics = policy.getMinMetrics();
+        assertEquals(0, minMetrics.length);
+    }
+
+    @Test
+    public void testGetMinMetrics_numericComplex() {
+        PasswordPolicy policy = testPolicy(PASSWORD_QUALITY_NUMERIC_COMPLEX);
+        PasswordMetrics minMetrics = policy.getMinMetrics();
+        assertEquals(CREDENTIAL_TYPE_PASSWORD, minMetrics.credType);
+        assertEquals(TEST_VALUE, minMetrics.length);
+        assertEquals(0, minMetrics.numeric);
+        assertEquals(0, minMetrics.letters);
+        assertEquals(0, minMetrics.lowerCase);
+        assertEquals(0, minMetrics.upperCase);
+        assertEquals(0, minMetrics.symbols);
+        assertEquals(0, minMetrics.nonLetter);
+        assertEquals(0, minMetrics.nonNumeric);
+        assertEquals(PasswordMetrics.MAX_ALLOWED_SEQUENCE, minMetrics.seqLength);
+    }
+
+    @Test
+    public void testGetMinMetrics_alphabetic() {
+        PasswordPolicy policy = testPolicy(PASSWORD_QUALITY_ALPHABETIC);
+        PasswordMetrics minMetrics = policy.getMinMetrics();
+        assertEquals(CREDENTIAL_TYPE_PASSWORD, minMetrics.credType);
+        assertEquals(TEST_VALUE, minMetrics.length);
+        assertEquals(0, minMetrics.numeric);
+        assertEquals(0, minMetrics.letters);
+        assertEquals(0, minMetrics.lowerCase);
+        assertEquals(0, minMetrics.upperCase);
+        assertEquals(0, minMetrics.symbols);
+        assertEquals(0, minMetrics.nonLetter);
+        assertEquals(1, minMetrics.nonNumeric);
+        assertEquals(Integer.MAX_VALUE, minMetrics.seqLength);
+    }
+
+    @Test
+    public void testGetMinMetrics_alphanumeric() {
+        PasswordPolicy policy = testPolicy(PASSWORD_QUALITY_ALPHANUMERIC);
+        PasswordMetrics minMetrics = policy.getMinMetrics();
+        assertEquals(CREDENTIAL_TYPE_PASSWORD, minMetrics.credType);
+        assertEquals(TEST_VALUE, minMetrics.length);
+        assertEquals(1, minMetrics.numeric);
+        assertEquals(0, minMetrics.letters);
+        assertEquals(0, minMetrics.lowerCase);
+        assertEquals(0, minMetrics.upperCase);
+        assertEquals(0, minMetrics.symbols);
+        assertEquals(0, minMetrics.nonLetter);
+        assertEquals(1, minMetrics.nonNumeric);
+        assertEquals(Integer.MAX_VALUE, minMetrics.seqLength);
+    }
+
+    @Test
+    public void testGetMinMetrics_complex() {
+        PasswordPolicy policy = testPolicy(PASSWORD_QUALITY_COMPLEX);
+        PasswordMetrics minMetrics = policy.getMinMetrics();
+        assertEquals(CREDENTIAL_TYPE_PASSWORD, minMetrics.credType);
+        assertEquals(TEST_VALUE, minMetrics.length);
+        assertEquals(TEST_VALUE, minMetrics.letters);
+        assertEquals(TEST_VALUE, minMetrics.lowerCase);
+        assertEquals(TEST_VALUE, minMetrics.upperCase);
+        assertEquals(TEST_VALUE, minMetrics.symbols);
+        assertEquals(TEST_VALUE, minMetrics.numeric);
+        assertEquals(TEST_VALUE, minMetrics.nonLetter);
+        assertEquals(0, minMetrics.nonNumeric);
+        assertEquals(Integer.MAX_VALUE, minMetrics.seqLength);
+    }
+
+    @Test
+    public void testGetMinMetrics_complexDefault() {
+        PasswordPolicy policy = new PasswordPolicy();
+        policy.quality = PASSWORD_QUALITY_COMPLEX;
+        PasswordMetrics minMetrics = policy.getMinMetrics();
+        assertEquals(CREDENTIAL_TYPE_PASSWORD, minMetrics.credType);
+        assertEquals(0, minMetrics.length);
+        assertEquals(1, minMetrics.letters);
+        assertEquals(0, minMetrics.lowerCase);
+        assertEquals(0, minMetrics.upperCase);
+        assertEquals(1, minMetrics.symbols);
+        assertEquals(1, minMetrics.numeric);
+        assertEquals(0, minMetrics.nonLetter);
+        assertEquals(0, minMetrics.nonNumeric);
+        assertEquals(Integer.MAX_VALUE, minMetrics.seqLength);
+    }
+
+    private PasswordPolicy testPolicy(int quality) {
+        PasswordPolicy result = new PasswordPolicy();
+        result.quality = quality;
+        result.length = TEST_VALUE;
+        result.letters = TEST_VALUE;
+        result.lowerCase = TEST_VALUE;
+        result.upperCase = TEST_VALUE;
+        result.numeric = TEST_VALUE;
+        result.symbols = TEST_VALUE;
+        result.nonLetter = TEST_VALUE;
+        return result;
+    }
+}
diff --git a/core/tests/coretests/src/android/util/TimestampedValueTest.java b/core/tests/coretests/src/android/util/TimestampedValueTest.java
index 6e3ab79..6fc2400 100644
--- a/core/tests/coretests/src/android/util/TimestampedValueTest.java
+++ b/core/tests/coretests/src/android/util/TimestampedValueTest.java
@@ -55,12 +55,12 @@
         TimestampedValue<String> stringValue = new TimestampedValue<>(1000, "Hello");
         Parcel parcel = Parcel.obtain();
         try {
-            TimestampedValue.writeToParcel(parcel, stringValue);
+            parcel.writeParcelable(stringValue, 0);
 
             parcel.setDataPosition(0);
 
             TimestampedValue<String> stringValueCopy =
-                    TimestampedValue.readFromParcel(parcel, null /* classLoader */, String.class);
+                    parcel.readParcelable(null /* classLoader */);
             assertEquals(stringValue, stringValueCopy);
         } finally {
             parcel.recycle();
@@ -72,12 +72,12 @@
         TimestampedValue<String> stringValue = new TimestampedValue<>(1000, "Hello");
         Parcel parcel = Parcel.obtain();
         try {
-            TimestampedValue.writeToParcel(parcel, stringValue);
+            parcel.writeParcelable(stringValue, 0);
 
             parcel.setDataPosition(0);
 
-            TimestampedValue<Object> stringValueCopy =
-                    TimestampedValue.readFromParcel(parcel, null /* classLoader */, Object.class);
+            TimestampedValue<String> stringValueCopy =
+                    parcel.readParcelable(null /* classLoader */);
             assertEquals(stringValue, stringValueCopy);
         } finally {
             parcel.recycle();
@@ -85,15 +85,15 @@
     }
 
     @Test
-    public void testParceling_valueClassIncompatible() {
-        TimestampedValue<String> stringValue = new TimestampedValue<>(1000, "Hello");
+    public void testParceling_valueClassNotParcelable() {
+        // This class is not one supported by Parcel.writeValue().
+        class NotParcelable {}
+
+        TimestampedValue<NotParcelable> notParcelableValue =
+                new TimestampedValue<>(1000, new NotParcelable());
         Parcel parcel = Parcel.obtain();
         try {
-            TimestampedValue.writeToParcel(parcel, stringValue);
-
-            parcel.setDataPosition(0);
-
-            TimestampedValue.readFromParcel(parcel, null /* classLoader */, Double.class);
+            parcel.writeParcelable(notParcelableValue, 0);
             fail();
         } catch (RuntimeException expected) {
         } finally {
@@ -106,12 +106,11 @@
         TimestampedValue<String> nullValue = new TimestampedValue<>(1000, null);
         Parcel parcel = Parcel.obtain();
         try {
-            TimestampedValue.writeToParcel(parcel, nullValue);
+            parcel.writeParcelable(nullValue, 0);
 
             parcel.setDataPosition(0);
 
-            TimestampedValue<Object> nullValueCopy =
-                    TimestampedValue.readFromParcel(parcel, null /* classLoader */, String.class);
+            TimestampedValue<String> nullValueCopy = parcel.readParcelable(null /* classLoader */);
             assertEquals(nullValue, nullValueCopy);
         } finally {
             parcel.recycle();
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
index abee1da2..7b405434 100644
--- a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
@@ -345,9 +345,9 @@
         accessibilityShortcutController.performAccessibilityShortcut();
         accessibilityShortcutController.performAccessibilityShortcut();
         verify(mToast).show();
-        assertEquals(WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS,
+        assertEquals(WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS,
                 mLayoutParams.privateFlags
-                        & WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS);
+                        & WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS);
         verify(mAccessibilityManagerService, times(1)).performAccessibilityShortcut();
     }
 
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index cc6eeed..5ea91da 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -284,7 +284,7 @@
         waitForIdle();
         UsageStatsManager usm = activity.getUsageStatsManager();
         verify(sOverrides.resolverListController, times(1))
-                .sort(Mockito.any(List.class));
+                .topK(Mockito.any(List.class), Mockito.anyInt());
         assertThat(activity.getIsSelected(), is(false));
         sOverrides.onSafelyStartCallback = targetInfo -> {
             return true;
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
index fcec00e..6218fa9 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
@@ -41,6 +41,8 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -112,13 +114,30 @@
         when(mMockContext.getSystemService(Context.USAGE_STATS_SERVICE)).thenReturn(mUsm);
         mController = new ResolverListController(mMockContext, mMockPackageManager, sendIntent,
                 refererPackage, UserHandle.USER_CURRENT);
-        mController.sort(new ArrayList<ResolverActivity.ResolvedComponentInfo>());
+        mController.sort(new ArrayList<ResolvedComponentInfo>());
         long beforeReport = getCount(mUsm, packageName, action, annotation);
         mController.updateChooserCounts(packageName, UserHandle.USER_CURRENT, action);
         long afterReport = getCount(mUsm, packageName, action, annotation);
         assertThat(afterReport, is(beforeReport + 1l));
     }
 
+    @Test
+    public void topKEqualsToSort() {
+        String annotation = "test_annotation";
+        Intent sendIntent = createSendImageIntent(annotation);
+        String refererPackage = "test_referer_package";
+        List<ResolvedComponentInfo> resolvedComponents = createResolvedComponentsForTest(15);
+        mUsm = new UsageStatsManager(mMockContext, mMockService);
+        when(mMockContext.getSystemService(Context.USAGE_STATS_SERVICE)).thenReturn(mUsm);
+        mController = new ResolverListController(mMockContext, mMockPackageManager, sendIntent,
+                refererPackage, UserHandle.USER_CURRENT);
+        List<ResolvedComponentInfo> topKList = new ArrayList<>(resolvedComponents);
+        mController.topK(topKList, 5);
+        List<ResolvedComponentInfo> sortList = new ArrayList<>(topKList);
+        mController.sort(sortList);
+        assertThat(sortList.subList(0, 5), is(topKList.subList(0, 5)));
+    }
+
     private UsageStats initStats(String packageName, String action,
                                  String annotation, int count) {
         ArrayMap<String, ArrayMap<String, Integer>> chooserCounts = new ArrayMap<>();
@@ -156,4 +175,12 @@
         }
         return packageStats.mChooserCounts.get(action).getOrDefault(annotation, 0);
     }
-}
\ No newline at end of file
+
+    private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
+        List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
+        for (int i = 0; i < numberOfResults; i++) {
+            infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
+        }
+        return infoList;
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/widget/LockscreenCredentialTest.java b/core/tests/coretests/src/com/android/internal/widget/LockscreenCredentialTest.java
new file mode 100644
index 0000000..5eec91c
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/widget/LockscreenCredentialTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.internal.widget;
+
+
+import android.test.AndroidTestCase;
+
+import java.util.Arrays;
+
+
+public class LockscreenCredentialTest extends AndroidTestCase {
+
+    public void testEmptyCredential() {
+        LockscreenCredential empty = LockscreenCredential.createNone();
+
+        assertTrue(empty.isNone());
+        assertEquals(0, empty.size());
+        assertNotNull(empty.getCredential());
+
+        assertFalse(empty.isPassword());
+        assertFalse(empty.isPattern());
+    }
+
+    public void testPasswordCredential() {
+        LockscreenCredential password = LockscreenCredential.createPassword("password");
+
+        assertTrue(password.isPassword());
+        assertEquals(8, password.size());
+        assertTrue(Arrays.equals("password".getBytes(), password.getCredential()));
+
+        assertFalse(password.isNone());
+        assertFalse(password.isPattern());
+    }
+
+    public void testPatternCredential() {
+        LockscreenCredential pattern = LockscreenCredential.createPattern(Arrays.asList(
+                LockPatternView.Cell.of(0, 0),
+                LockPatternView.Cell.of(0, 1),
+                LockPatternView.Cell.of(0, 2),
+                LockPatternView.Cell.of(1, 2),
+                LockPatternView.Cell.of(2, 2)
+                ));
+
+        assertTrue(pattern.isPattern());
+        assertEquals(5, pattern.size());
+        assertTrue(Arrays.equals("12369".getBytes(), pattern.getCredential()));
+
+        assertFalse(pattern.isNone());
+        assertFalse(pattern.isPassword());
+    }
+
+    public void testPasswordOrNoneCredential() {
+        assertEquals(LockscreenCredential.createNone(),
+                LockscreenCredential.createPasswordOrNone(null));
+        assertEquals(LockscreenCredential.createNone(),
+                LockscreenCredential.createPasswordOrNone(""));
+        assertEquals(LockscreenCredential.createPassword("abcd"),
+                LockscreenCredential.createPasswordOrNone("abcd"));
+    }
+
+    public void testSanitize() {
+        LockscreenCredential password = LockscreenCredential.createPassword("password");
+        password.zeroize();
+
+        try {
+            password.isNone();
+            fail("Sanitized credential still accessible");
+        } catch (IllegalStateException expected) { }
+
+        try {
+            password.isPattern();
+            fail("Sanitized credential still accessible");
+        } catch (IllegalStateException expected) { }
+        try {
+            password.isPassword();
+            fail("Sanitized credential still accessible");
+        } catch (IllegalStateException expected) { }
+        try {
+            password.size();
+            fail("Sanitized credential still accessible");
+        } catch (IllegalStateException expected) { }
+        try {
+            password.getCredential();
+            fail("Sanitized credential still accessible");
+        } catch (IllegalStateException expected) { }
+    }
+
+    public void testEquals() {
+        assertEquals(LockscreenCredential.createNone(), LockscreenCredential.createNone());
+        assertEquals(LockscreenCredential.createPassword("1234"),
+                LockscreenCredential.createPassword("1234"));
+        assertEquals(LockscreenCredential.createPin("4321"),
+                LockscreenCredential.createPin("4321"));
+        assertEquals(createPattern("1234"), createPattern("1234"));
+
+        assertNotSame(LockscreenCredential.createPassword("1234"),
+                LockscreenCredential.createNone());
+        assertNotSame(LockscreenCredential.createPassword("1234"),
+                LockscreenCredential.createPassword("4321"));
+        assertNotSame(LockscreenCredential.createPassword("1234"),
+                createPattern("1234"));
+        assertNotSame(LockscreenCredential.createPassword("1234"),
+                LockscreenCredential.createPin("1234"));
+
+        assertNotSame(LockscreenCredential.createPin("1111"),
+                LockscreenCredential.createNone());
+        assertNotSame(LockscreenCredential.createPin("1111"),
+                LockscreenCredential.createPin("2222"));
+        assertNotSame(LockscreenCredential.createPin("1111"),
+                createPattern("1111"));
+        assertNotSame(LockscreenCredential.createPin("1111"),
+                LockscreenCredential.createPassword("1111"));
+
+        assertNotSame(createPattern("5678"),
+                LockscreenCredential.createNone());
+        assertNotSame(createPattern("5678"),
+                createPattern("1234"));
+        assertNotSame(createPattern("5678"),
+                LockscreenCredential.createPassword("5678"));
+        assertNotSame(createPattern("5678"),
+                LockscreenCredential.createPin("5678"));
+    }
+
+    public void testDuplicate() {
+        LockscreenCredential credential;
+
+        credential = LockscreenCredential.createNone();
+        assertEquals(credential, credential.duplicate());
+        credential = LockscreenCredential.createPassword("abcd");
+        assertEquals(credential, credential.duplicate());
+        credential = LockscreenCredential.createPin("1234");
+        assertEquals(credential, credential.duplicate());
+        credential = createPattern("5678");
+        assertEquals(credential, credential.duplicate());
+    }
+
+    private LockscreenCredential createPattern(String patternString) {
+        return LockscreenCredential.createPattern(LockPatternUtils.byteArrayToPattern(
+                patternString.getBytes()));
+    }
+}
diff --git a/data/etc/framework-sysconfig.xml b/data/etc/framework-sysconfig.xml
index 987c3b4..7296cfd 100644
--- a/data/etc/framework-sysconfig.xml
+++ b/data/etc/framework-sysconfig.xml
@@ -29,6 +29,8 @@
          'service' attribute here is a flattened ComponentName string. -->
     <backup-transport-whitelisted-service
         service="com.android.localtransport/.LocalTransportService" />
+    <backup-transport-whitelisted-service
+        service="com.android.encryptedlocaltransport/.EncryptedLocalTransportService" />
 
     <!-- Whitelist Shell to use the bugreport API -->
     <bugreport-whitelisted package="com.android.shell" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 10f6b69..ac742e2 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -50,6 +50,12 @@
         <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
     </privapp-permissions>
 
+    <privapp-permissions package="com.android.cellbroadcastservice">
+        <permission name="android.permission.MODIFY_PHONE_STATE"/>
+        <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+        <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
+    </privapp-permissions>
+
     <privapp-permissions package="com.android.externalstorage">
         <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
         <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
@@ -121,6 +127,7 @@
         <permission name="android.permission.APPROVE_INCIDENT_REPORTS"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
         <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
+        <permission name="android.permission.PACKAGE_USAGE_STATS" />
     </privapp-permissions>
 
     <privapp-permissions package="com.android.phone">
@@ -359,6 +366,7 @@
         <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
         <permission name="android.permission.DUMP"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+        <permission name="android.permission.INTERNAL_SYSTEM_WINDOW"/>
         <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
         <permission name="android.permission.MANAGE_USERS"/>
         <permission name="android.permission.PACKAGE_USAGE_STATS"/>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 34b3951..8508f7c 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1,30 +1,6 @@
 {
   "version": "1.0.0",
   "messages": {
-    "-2146181682": {
-      "message": "Releasing screen wakelock, obscured by %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_KEEP_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-2138637148": {
-      "message": "Clearing focused app, displayId=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/ActivityDisplay.java"
-    },
-    "-2109864870": {
-      "message": "app-release(): mOuter=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "-2086729999": {
-      "message": "Removing app token: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-2072089308": {
       "message": "Attempted to add window with token that is a sub-window: %s.  Aborting.",
       "level": "WARN",
@@ -37,234 +13,48 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-2024464438": {
-      "message": "app-onAnimationFinished(): mOuter=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "-2012562539": {
-      "message": "startAnimation(): Notify animation start:",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "-2002500255": {
-      "message": "Defer removing snapshot surface in %dms",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/TaskSnapshotSurface.java"
-    },
-    "-1991255017": {
-      "message": "Drawing snapshot surface sizeMismatch=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/TaskSnapshotSurface.java"
-    },
     "-1976930686": {
       "message": "Attempted to add Accessibility overlay window with bad token %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1963461591": {
-      "message": "Removing %s from %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-1958209312": {
-      "message": "Clear freezing of %s: hidden=%b freezing=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/ActivityRecord.java"
-    },
-    "-1953668890": {
-      "message": "Can't start recents animation, nextAppTransition=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
     "-1949279037": {
       "message": "Attempted to add input method window with bad token %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1939358269": {
-      "message": "mRecentScreenshotAnimator finish",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
-    },
-    "-1938839202": {
-      "message": "SURFACE LEAK DESTROY: %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
     "-1915280162": {
       "message": "Attempted to add wallpaper window with bad token %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1886298021": {
-      "message": "setAppStartingWindow: token=%s pkg=%s transferFrom=%s newTask=%b taskSwitch=%b processRunning=%b allowTaskSnapshot=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/ActivityRecord.java"
-    },
-    "-1884933373": {
-      "message": "enableScreenAfterBoot: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s",
-      "level": "INFO",
-      "group": "WM_DEBUG_BOOT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-1872288685": {
-      "message": "applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppTransition.java"
-    },
-    "-1868124841": {
-      "message": "screenOnEarly=%b, awake=%b, currentAppOrientation=%d, orientationSensorEnabled=%b, keyguardDrawComplete=%b, windowManagerDrawComplete=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
-    "-1862269827": {
-      "message": "applyAnimation: anim=%s transit=%s isEntrance=%b Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppTransition.java"
-    },
     "-1838803135": {
       "message": "Attempted to set windowing mode to a display that does not exist: %d",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1836092044": {
-      "message": "Creating SnapshotStartingData",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-1824578273": {
-      "message": "Reporting new frame to %s: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_RESIZE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "-1822611824": {
-      "message": "\tRemove token=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "-1797409732": {
-      "message": "Skipping %s because %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
     "-1770075711": {
       "message": "Adding window client %s that is dead, aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1768557332": {
-      "message": "removeWallpaperAnimation()",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
-    },
     "-1750206390": {
       "message": "Exception thrown when creating surface for client %s (%s). %s",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1747461042": {
-      "message": "set mOrientationChanging of %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "-1741065110": {
-      "message": "No app is requesting an orientation, return %d for display id=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
-    "-1736245181": {
-      "message": "Tried to remove starting window but startingWindow was null: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-1730156332": {
-      "message": "Display id=%d rotation changed to %d from %d, lastOrientation=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
-    "-1710206702": {
-      "message": "Display id=%d is frozen while keyguard locked, return %d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
     "-1661704580": {
       "message": "Attempted to set replacing window on non-existing app token %s",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1661404819": {
-      "message": "applyAnimation: atoken=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-1632122349": {
-      "message": "Changing surface while display frozen: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-1597650595": {
-      "message": "removeAppToken: %s delayed=%b Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-1596995693": {
-      "message": "startAnimation",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "-1587841219": {
-      "message": "Focus moving from %s to %s displayId=%d",
-      "level": "INFO",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-1568331821": {
-      "message": "Enabling listeners",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
-    "-1561845439": {
-      "message": "reParentWindowToken: removing window token=%s from task=%s",
-      "level": "INFO",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-1545962566": {
       "message": "View server did not start",
       "level": "WARN",
@@ -277,306 +67,54 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1524305318": {
-      "message": "Nulling last startingData",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-1519226370": {
-      "message": "startingData was nulled out before handling mAddStartingWindow: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-1515151503": {
-      "message": ">>> OPEN TRANSACTION removeReplacedWindows",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
-    },
-    "-1497837552": {
-      "message": "onAnimationFinished(): mPendingAnimations=%d",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "-1483752006": {
-      "message": "  THUMBNAIL %s: CREATE",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/AppWindowThumbnail.java"
-    },
-    "-1470632028": {
-      "message": "Marking app token %s with replacing windows.",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-1455600136": {
       "message": "Attempted to add Dream window with unknown token %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1448427933": {
-      "message": "startingWindow was set but startingSurface==null, couldn't remove",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-1443029505": {
       "message": "SAFE MODE ENABLED (menu=%d s=%d dpad=%d trackball=%d)",
       "level": "INFO",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1434147454": {
-      "message": "cleanupAnimation(): Notify animation finished mPendingAnimations=%d reorderMode=%d",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
-    },
-    "-1427184084": {
-      "message": "addWindow: New client %s: window=%s Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-1413901262": {
-      "message": "startRecentsActivity(): intent=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
-    "-1391944764": {
-      "message": "SURFACE DESTROY: %s. %s",
-      "level": "INFO",
-      "group": "WM_SHOW_SURFACE_ALLOC",
-      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
-    },
     "-1389772804": {
       "message": "Attempted to add voice interaction window with bad token %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1350198040": {
-      "message": "hideBootMessagesLocked: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s",
-      "level": "INFO",
-      "group": "WM_DEBUG_BOOT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-1318134223": {
-      "message": "No longer Stopped: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-1270731689": {
       "message": "Attempted to set replacing window on app token with no content %s",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1270148832": {
-      "message": "Resize start waiting for draw, mDrawState=DRAW_PENDING in %s, surfaceController %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_RESIZE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
     "-1263554915": {
       "message": "Attempted to add Dream window with bad token %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1259022216": {
-      "message": "SURFACE HIDE ( %s ): %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
-    },
-    "-1257821162": {
-      "message": "OUT SURFACE %s: copied",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-1219773477": {
-      "message": "setInputConsumerEnabled(%s): mCanceled=%b",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
-    },
-    "-1207757583": {
-      "message": "startAnimation(): Notify animation start: %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
-    },
-    "-1176488860": {
-      "message": "SURFACE isSecure=%b: %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
-    },
-    "-1156118957": {
-      "message": "Updated config=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
-    "-1144293044": {
-      "message": "SURFACE SET FREEZE LAYER: %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
-    },
-    "-1130891072": {
-      "message": "Orientation continue waiting for draw in %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
-    },
-    "-1130868271": {
-      "message": "Resizing %s WITH DRAW PENDING",
-      "level": "INFO",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "-1117599386": {
-      "message": "Deferring rotation, display is not enabled.",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
     "-1113134997": {
       "message": "Attempted to add application window with unknown token %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1103716954": {
-      "message": "Not removing %s due to exit animation",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "-1103115659": {
-      "message": "Performing post-rotate rotation",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
-    },
-    "-1099052739": {
-      "message": "\tAdd token=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "-1097148233": {
-      "message": "commitVisibility: %s: hidden=%b hiddenRequested=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-1089874824": {
-      "message": "SURFACE SHOW (performLayout): %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
-    },
-    "-1077196445": {
-      "message": "Add starting %s: startingData=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-1076978367": {
-      "message": "thawRotation: mRotation=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
     "-1060365734": {
       "message": "Attempted to add QS dialog window with bad token %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1047945589": {
-      "message": "Remove client=%x, surfaceController=%s Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "-1044506655": {
-      "message": "New transit away from wallpaper: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
     "-1042574499": {
       "message": "Attempted to add Accessibility overlay window with unknown token %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1009117329": {
-      "message": "isFetchingAppTransitionSpecs=true",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
-    "-1001633850": {
-      "message": "Removing focused app token:%s displayId=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-993378225": {
-      "message": "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_DRAW",
-      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
-    },
-    "-986746907": {
-      "message": "Starting window removed %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "-979259577": {
-      "message": "setAppVisibility(%s, visible=%b): %s hidden=%b hiddenRequested=%b Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-955458843": {
-      "message": "Set freezing of %s: hidden=%b freezing=%b hiddenRequested=%b. %s",
-      "level": "INFO",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-953872371": {
-      "message": "setClientHidden: %s clientHidden=%b Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-928291778": {
-      "message": "applyAnimation: anim=%s nextAppTransition=%d transit=%s Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppTransition.java"
-    },
-    "-916108501": {
-      "message": "Adding %s to %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
     "-914253865": {
       "message": "Attempted to add voice interaction window with unknown token %s.  Aborting.",
       "level": "WARN",
@@ -589,198 +127,36 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-874446906": {
-      "message": "showBootMessage: msg=%s always=%b mAllowBootMessages=%b mShowingBootMessages=%b mSystemBooted=%b. %s",
-      "level": "INFO",
-      "group": "WM_DEBUG_BOOT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
     "-861859917": {
       "message": "Attempted to add window to a display that does not exist: %d. Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-861707633": {
-      "message": "Destroying surface %s called by %s",
-      "level": "INFO",
-      "group": "WM_SHOW_SURFACE_ALLOC",
-      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
-    },
-    "-856025122": {
-      "message": "SURFACE transparentRegionHint=%s: %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-853404763": {
-      "message": "\twallpaper=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
     "-853226675": {
       "message": "Attempted to add window with exiting application token .%s Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-809771899": {
-      "message": "findFocusedWindow: Reached focused app=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
-    "-807062773": {
-      "message": "Aborted starting %s: removed=%b startingData=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-793346159": {
-      "message": "New transit into wallpaper: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
     "-784959154": {
       "message": "Attempted to add private presentation window to a non-private display.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-783405930": {
-      "message": "Performing post-rotate rotation",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-771282525": {
-      "message": "Losing focus: %s",
-      "level": "INFO",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-760801764": {
-      "message": "onAnimationCancelled",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java"
-    },
-    "-754503024": {
-      "message": "Relayout %s: oldVis=%d newVis=%d. %s",
-      "level": "INFO",
-      "group": "WM_DEBUG_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
     "-747671114": {
       "message": "Failed looking up window callers=%s",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-714291355": {
-      "message": "Losing delayed focus: %s",
-      "level": "INFO",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-694710814": {
-      "message": "Pausing rotation during drag",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DragState.java"
-    },
-    "-687185281": {
-      "message": "New topFocusedDisplayId=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
-    },
-    "-666510420": {
-      "message": "With display frozen, orientationChangeComplete=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
-    },
-    "-666419717": {
-      "message": "Creating animation bounds layer",
-      "level": "INFO",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-653156702": {
-      "message": "createAppAnimations()",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "-650040763": {
-      "message": "rotationForOrientation(orient=%d, last=%d); user=%d %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
-    "-635082269": {
-      "message": "******** booted=%b msg=%b haveBoot=%b haveApp=%b haveWall=%b wallEnabled=%b haveKeyguard=%b",
-      "level": "INFO",
-      "group": "WM_DEBUG_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
-    "-622997754": {
-      "message": "postWindowRemoveCleanupLocked: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-618015844": {
-      "message": "performEnableScreen: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b mOnlyCore=%b. %s",
-      "level": "INFO",
-      "group": "WM_DEBUG_BOOT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
     "-583031528": {
       "message": "%s",
       "level": "INFO",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-576070986": {
-      "message": "Performing post-rotate rotation after seamless rotation",
-      "level": "INFO",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
-    "-573268667": {
-      "message": "applyAnimation: transition animation is disabled or skipped. atoken=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-554834595": {
-      "message": "Display id=%d is frozen, return %d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
-    "-549028919": {
-      "message": "enableScreenIfNeededLocked: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s",
-      "level": "INFO",
-      "group": "WM_DEBUG_BOOT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-545190927": {
-      "message": "<<< CLOSE TRANSACTION animate",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowAnimator.java"
-    },
-    "-519504830": {
-      "message": "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM transit=%s isEntrance=%b Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppTransition.java"
-    },
     "-507657818": {
       "message": "Window %s is already added",
       "level": "WARN",
@@ -793,54 +169,6 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-481924678": {
-      "message": "handleNotObscuredLocked w: %s, w.mHasSurface: %b, w.isOnScreen(): %b, w.isDisplayedLw(): %b, w.mAttrs.userActivityTimeout: %d",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_KEEP_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
-    },
-    "-477481651": {
-      "message": "SURFACE DESTROY PENDING: %s. %s",
-      "level": "INFO",
-      "group": "WM_SHOW_SURFACE_ALLOC",
-      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
-    },
-    "-445944810": {
-      "message": "finish(%b): mCanceled=%b",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
-    },
-    "-444624452": {
-      "message": "REPARENT from: %s to: %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
-    },
-    "-439951996": {
-      "message": "Disabling listeners",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
-    "-415912575": {
-      "message": "setTask: %s at top.",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/ActivityRecord.java"
-    },
-    "-415865166": {
-      "message": "findFocusedWindow: Found new focus @ %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
-    "-405536909": {
-      "message": "Removing snapshot surface",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/TaskSnapshotSurface.java"
-    },
     "-393505149": {
       "message": "unable to update pointer icon",
       "level": "WARN",
@@ -853,198 +181,42 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-379068494": {
-      "message": "unknownApps is not empty: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
-    "-371630969": {
-      "message": "New wallpaper target=%s, oldWallpaper=%s, openingApps=%s, closingApps=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
-    "-367797467": {
-      "message": "Creating SplashScreenStartingData",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-344488673": {
-      "message": "Finishing drawing window %s: mDrawState=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
-    },
-    "-336658140": {
-      "message": "Checking theme of starting window: 0x%x",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-324085783": {
-      "message": "SURFACE CROP %s: %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
-    },
     "-322035974": {
       "message": "App freeze timeout expired.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-320419645": {
-      "message": "Removing replaced window: %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "-198463978": {
-      "message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-193782861": {
-      "message": "Final remove of window: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_WINDOW_MOVEMENT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
     "-167822951": {
       "message": "Attempted to add starting window to token with already existing starting window",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-129722369": {
-      "message": "New transit: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
-    "-121104356": {
-      "message": "Remove %s: mSurfaceController=%s mAnimatingExit=%b mRemoveOnExit=%b mHasSurface=%b surfaceShowing=%b animating=%b app-animation=%b mWillReplaceWindow=%b inPendingTransaction=%b mDisplayFrozen=%b callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "-116086365": {
-      "message": "******************** ENABLING SCREEN!",
-      "level": "INFO",
-      "group": "WM_DEBUG_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-106400104": {
-      "message": "Preload recents with %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
-    "-104758113": {
-      "message": "Removing app %s delayed=%b animation=%s animating=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-96848838": {
-      "message": "Gaining focus: %s",
-      "level": "INFO",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "-87705714": {
-      "message": "findFocusedWindow: focusedApp=null using new focus @ %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
     "-87703044": {
       "message": "Boot completed: SurfaceFlinger is dead!",
       "level": "ERROR",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-86763148": {
-      "message": "  KILL SURFACE SESSION %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/Session.java"
-    },
-    "-34965929": {
-      "message": "Moving pending starting from %s to %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-29233992": {
-      "message": "SURFACE CLEAR CROP: %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
-    },
-    "-7343917": {
-      "message": "onAnimationFinished(): targetStack=%s targetActivity=%s mRestoreTargetBehindStack=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
-    "9803449": {
-      "message": "startFreezingDisplayLocked: exitAnim=%d enterAnim=%d called by %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "10608884": {
-      "message": "  FREEZE %s: CREATE",
-      "level": "INFO",
-      "group": "WM_SHOW_SURFACE_ALLOC",
-      "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java"
-    },
     "11060725": {
       "message": "Attempted to get system decors flag of a display that does not exist: %d",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "17696244": {
-      "message": "startAnimation(): mPendingStart=%b mCanceled=%b",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
-    },
     "38267433": {
       "message": "Attempted to reset replacing window on non-existing app token %s",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "44171776": {
-      "message": "Resetting app token %s of replacing window marks.",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "51200510": {
-      "message": "  BLACK %s: DESTROY",
-      "level": "INFO",
-      "group": "WM_SHOW_SURFACE_ALLOC",
-      "at": "com\/android\/server\/wm\/BlackFrame.java"
-    },
     "51628177": {
       "message": "Attempted to get windowing mode of a display that does not exist: %d",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "83950285": {
-      "message": "removeAnimation(%d)",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
-    },
     "91350919": {
       "message": "Attempted to set IME flag to a display that does not exist: %d",
       "level": "WARN",
@@ -1057,222 +229,36 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "95902367": {
-      "message": "Relayout of %s: focusMayChange=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "100936473": {
-      "message": "Wallpaper animation!",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
-    "115108840": {
-      "message": "Removing startingView=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "118187173": {
-      "message": "Enqueueing ADD_STARTING",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "123161180": {
-      "message": "SEVER CHILDREN",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
-    },
-    "150351993": {
-      "message": "addWindow: %s startingWindow=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "152914409": {
-      "message": "  BLACK %s: CREATE layer=%d",
-      "level": "INFO",
-      "group": "WM_SHOW_SURFACE_ALLOC",
-      "at": "com\/android\/server\/wm\/BlackFrame.java"
-    },
-    "154699456": {
-      "message": "Last window, removing starting window %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "173419252": {
-      "message": "No thumbnail header bitmap for: %d",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "184362060": {
-      "message": "screenshotTask(%d): mCanceled=%b",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
-    },
-    "186668272": {
-      "message": "Now changing app %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
-    "194124419": {
-      "message": "goodToGo(): Animation finished already, canceled=%s mPendingAnimations=%d",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "196230599": {
-      "message": "Moving existing starting %s from %s to %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "221540118": {
-      "message": "mUserActivityTimeout set to %d",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_KEEP_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
-    },
-    "241961619": {
-      "message": "Adding %s to %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowToken.java"
-    },
     "246676969": {
       "message": "Attempted to add window with non-application token .%s Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "248210157": {
-      "message": "Finishing remote animation",
-      "level": "INFO",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
     "254883724": {
       "message": "addWindowToken: Attempted to add binder token: %s for already created window token: %s displayId=%d",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "255692476": {
-      "message": "**** GOOD TO GO",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
-    "269576220": {
-      "message": "Resuming rotation after drag",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DragState.java"
-    },
-    "274773837": {
-      "message": "applyAnimation: anim=%s nextAppTransition=ANIM_CLIP_REVEAL transit=%s Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppTransition.java"
-    },
-    "285317231": {
-      "message": "Input focus has changed to %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/InputMonitor.java"
-    },
     "288485303": {
       "message": "Attempted to set remove mode to a display that does not exist: %d",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "289967521": {
-      "message": "Check opening app=%s: allDrawn=%b startingDisplayed=%b startingMoved=%b isRelaunching()=%b startingWindow=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
-    "292904800": {
-      "message": "Deferring rotation, animation in progress.",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
-    "302992539": {
-      "message": "addAnimation(%s)",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
-    },
-    "309039362": {
-      "message": "SURFACE MATRIX [%f,%f,%f,%f]: %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
-    },
-    "342460966": {
-      "message": "DRAG %s: pos=(%d,%d)",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/DragState.java"
-    },
-    "344795667": {
-      "message": "*** APP TRANSITION TIMEOUT. displayId=%d isTransitionSet()=%b mOpeningApps.size()=%d mClosingApps.size()=%d mChangingApps.size()=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransition.java"
-    },
-    "355720268": {
-      "message": "stopFreezingDisplayLocked: Unfreezing now",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
     "371641947": {
       "message": "Window Manager Crash %s",
       "level": "WTF",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "374972436": {
-      "message": "performEnableScreen: Waiting for anim complete",
-      "level": "INFO",
-      "group": "WM_DEBUG_BOOT",
+    "372792199": {
+      "message": "Non-null activity for system window of rootType=%d",
+      "level": "WARN",
+      "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "385096046": {
-      "message": "Delaying loss of focus...",
-      "level": "INFO",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "399841913": {
-      "message": "SURFACE RECOVER DESTROY: %s",
-      "level": "INFO",
-      "group": "WM_SHOW_SURFACE_ALLOC",
-      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
-    },
-    "416664944": {
-      "message": "No longer freezing: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "417311568": {
-      "message": "onResize: Resizing %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RESIZE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
     "424524729": {
       "message": "Attempted to add wallpaper window with unknown token %s.  Aborting.",
       "level": "WARN",
@@ -1285,600 +271,108 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "457951957": {
-      "message": "\tNot visible=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java"
-    },
-    "463993897": {
-      "message": "Aborted waiting for drawn: %s",
-      "level": "WARN",
-      "group": "WM_DEBUG_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "474000473": {
-      "message": "No stack above target stack=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
-    "481370485": {
-      "message": "Computed rotation=%d for display id=%d based on lastOrientation=%d and oldRotation=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
-    "490877640": {
-      "message": "onStackOrderChanged(): stack=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
-    "492980365": {
-      "message": "TRANSIT_TASK_OPEN_BEHIND,  adding %s to mOpeningApps",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "495032901": {
-      "message": "Expected target stack=%s to restored behind stack=%s but it is behind stack=%s",
-      "level": "WARN",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
-    "508887531": {
-      "message": "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppTransition.java"
-    },
-    "557227556": {
-      "message": "onAnimationFinished(): Notify animation finished:",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "558823034": {
-      "message": "SURFACE isOpaque=%b: %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
-    },
-    "585096182": {
-      "message": "SURFACE isColorSpaceAgnostic=%b: %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
-    },
-    "594260577": {
-      "message": "createWallpaperAnimations()",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "600140673": {
-      "message": "checkBootAnimationComplete: Waiting for anim complete",
-      "level": "INFO",
-      "group": "WM_DEBUG_BOOT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "608694300": {
-      "message": "  NEW SURFACE SESSION %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/Session.java"
-    },
     "620368427": {
       "message": "******* TELLING SURFACE FLINGER WE ARE BOOTED!",
       "level": "INFO",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "628276090": {
-      "message": "Delaying app transition for screen rotation animation to finish",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
     "631792420": {
       "message": "Attempted to add window with token that is not a window: %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "633654009": {
-      "message": "SURFACE POS (setPositionInTransaction) @ (%f,%f): %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
-    },
-    "644675193": {
-      "message": "Real start recents",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
-    "646155519": {
-      "message": "Started intent=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
     "662572728": {
       "message": "Attempted to add a toast window with bad token %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "665256544": {
-      "message": "All windows drawn!",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "668425960": {
-      "message": "Notify removed startingWindow %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "676824470": {
       "message": "Test completed successfully: %b %d %o %x %e %g %f %% %s.",
       "level": "ERROR",
       "group": "TEST_GROUP",
       "at": "com\/android\/server\/wm\/ProtoLogGroup.java"
     },
-    "685047360": {
-      "message": "Resizing window %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_RESIZE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "690411811": {
-      "message": "goodToGo(): No apps to animate",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "693423992": {
-      "message": "setAnimationLocked: setting mFocusMayChange true",
-      "level": "INFO",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
     "704998117": {
       "message": "Failed to create surface control for %s",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "745391677": {
-      "message": "  CREATE SURFACE %s IN SESSION %s: pid=%d format=%d flags=0x%x \/ %s",
-      "level": "INFO",
-      "group": "WM_SHOW_SURFACE_ALLOC",
-      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
-    },
-    "758852025": {
-      "message": "Surface returned was null: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "765395228": {
-      "message": "onAnimationFinished(): controller=%s reorderMode=%d",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
-    "791468751": {
-      "message": "Pausing rotation during re-position",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/TaskPositioner.java"
-    },
-    "794570322": {
-      "message": "Now closing app %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
-    "811802785": {
-      "message": "Changing app %s hidden=%b performLayout=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "829434921": {
-      "message": "Draw state now committed in %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
-    },
-    "835814848": {
-      "message": "%s",
-      "level": "INFO",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "845234215": {
-      "message": "App is requesting an orientation, return %d for display id=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
-    "847534382": {
-      "message": "Non-null appWindowToken for system window of rootType=%d",
-      "level": "WARN",
-      "group": "WM_ERROR",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "853091290": {
-      "message": "Moved stack=%s behind stack=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
-    "868946719": {
-      "message": "notifyAppResumed: wasStopped=%b %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "873914452": {
-      "message": "goodToGo()",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "884043983": {
-      "message": "removeDeadWindows: %s",
-      "level": "WARN",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "892244061": {
-      "message": "Waiting for drawn %s: removed=%b visible=%b mHasSurface=%b drawState=%d",
-      "level": "INFO",
-      "group": "WM_DEBUG_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
     "898863925": {
       "message": "Attempted to add QS dialog window with unknown token %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "913494177": {
-      "message": "removeAllWindowsIfPossible: removing win=%s",
-      "level": "WARN",
-      "group": "WM_DEBUG_WINDOW_MOVEMENT",
-      "at": "com\/android\/server\/wm\/WindowToken.java"
-    },
-    "916191774": {
-      "message": "Orientation change complete in %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
-    },
-    "917739349": {
-      "message": "Set focused app to: %s moveFocusNow=%b displayId=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/ActivityDisplay.java"
-    },
     "954470154": {
       "message": "FORCED DISPLAY SCALING DISABLED",
       "level": "INFO",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "990058731": {
-      "message": "notifyAppStopped: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "1001904964": {
       "message": "***** BOOT TIMEOUT: forcing display enabled",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1004585481": {
-      "message": "%s forcing orientation to %d for display id=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
-    "1021057640": {
-      "message": "Marking app token %s with replacing child windows.",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "1051545910": {
-      "message": "Exit animation finished in %s: remove=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "1073230342": {
-      "message": "startAnimation",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java"
-    },
-    "1089714158": {
-      "message": "  FREEZE %s: DESTROY",
-      "level": "INFO",
-      "group": "WM_SHOW_SURFACE_ALLOC",
-      "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java"
-    },
-    "1108406230": {
-      "message": "stopFreezingDisplayLocked: Returning mWaitingForConfig=%b, mAppsFreezingScreen=%d, mWindowsFreezingScreen=%d, mClientFreezingScreen=%b, mOpeningApps.size()=%d",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "1112047265": {
-      "message": "finishDrawingWindow: %s mDrawState=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
     "1115417974": {
       "message": "FORCED DISPLAY SIZE: %dx%d",
       "level": "INFO",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1140424002": {
-      "message": "Finished screen turning on...",
-      "level": "INFO",
-      "group": "WM_DEBUG_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/DisplayPolicy.java"
-    },
-    "1160771501": {
-      "message": "Resize reasons for w=%s:  %s surfaceResized=%b configChanged=%b dragResizingChanged=%b reportOrientationChanged=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_RESIZE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "1166381079": {
-      "message": "Execute app transition: %s, displayId: %d Callers=%s",
-      "level": "WARN",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
-    "1195433019": {
-      "message": "Clearing startingData for token=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "1208313423": {
       "message": "addWindowToken: Attempted to add token: %s for non-exiting displayId=%d",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1219600119": {
-      "message": "addWindow: win=%s Callers=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_FOCUS",
-      "at": "com\/android\/server\/wm\/WindowToken.java"
-    },
-    "1220075598": {
-      "message": "SURFACE SIZE %dx%d: %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
-    },
-    "1224307091": {
-      "message": "checkBootAnimationComplete: Animation complete!",
-      "level": "INFO",
-      "group": "WM_DEBUG_BOOT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "1244668962": {
-      "message": "Added starting %s: startingWindow=%s startingView=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "1288731814": {
-      "message": "WindowState.hideLw: setting mFocusMayChange true",
-      "level": "INFO",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
     "1325649102": {
       "message": "Bad requesting window %s",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1329340614": {
-      "message": "Orientation not waiting for draw in %s, surfaceController %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
     "1331177619": {
       "message": "Attempted to add a toast window with unknown token %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1358462645": {
-      "message": "Looking for focus: %s, flags=%d, canReceive=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
-    "1401700824": {
-      "message": "Window drawn win=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "1404220922": {
-      "message": "Translucent=%s Floating=%s ShowWallpaper=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "1422781269": {
-      "message": "Resuming rotation after re-position",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/TaskPositioner.java"
-    },
     "1423418408": {
       "message": "unable to restore pointer icon",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1423592961": {
-      "message": "<<< CLOSE TRANSACTION removeReplacedWindows",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
-    },
-    "1430336882": {
-      "message": "findFocusedWindow: focusedApp windows not focusable using new focus @ %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
     "1434383382": {
       "message": "Attempted to get flag of a display that does not exist: %d",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1448683958": {
-      "message": "Override pending remote transitionSet=%b adapter=%s",
-      "level": "INFO",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransition.java"
-    },
-    "1457990604": {
-      "message": "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM_IN_PLACE transit=%s Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppTransition.java"
-    },
-    "1469292670": {
-      "message": "Changing focus from %s to %s displayId=%d Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
-    "1495525537": {
-      "message": "createWallpaperAnimations()",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
-    },
-    "1496418389": {
-      "message": "Removing starting %s from %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "1497304204": {
-      "message": "Deferring rotation, rotation is paused.",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
-    "1504168072": {
-      "message": "removeIfPossible: %s callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
     "1518495446": {
       "message": "removeWindowToken: Attempted to remove non-existing token: %s",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1519757176": {
-      "message": "setHomeApp(%s)",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
-    },
     "1521476038": {
       "message": "Attempted to set flag to a display that does not exist: %d",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1525976603": {
-      "message": "cancelAnimation(): reason=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
-    },
-    "1531527061": {
-      "message": "createAnimationAdapter(): token=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
     "1563755163": {
       "message": "Permission Denial: %s from pid=%d, uid=%d requires %s",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1573332272": {
-      "message": "Display id=%d selected orientation %d, got rotation %d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
-    "1577579529": {
-      "message": "win=%s destroySurfaces: appStopped=%b win.mWindowRemovalAllowed=%b win.mRemoveOnExit=%b",
-      "level": "ERROR",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "1589610525": {
-      "message": "applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS: anim=%s transit=%s isEntrance=true Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppTransition.java"
-    },
-    "1628345525": {
-      "message": "Now opening app %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
-    "1634557978": {
-      "message": "**** Dismissing screen rotation animation",
-      "level": "INFO",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "1635462459": {
-      "message": "onMovedByResize: Moving %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RESIZE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "1637745145": {
-      "message": "Clear freezing of %s force=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "1720696061": {
       "message": "Adding window to Display that has been removed.",
       "level": "WARN",
@@ -1891,280 +385,31 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1747941491": {
-      "message": "SURFACE controller=%s alpha=%f matrix=[%f*%f,%f*%f][%f*%f,%f*%f]: %s",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
-    },
-    "1756082882": {
-      "message": "Orientation change skips hidden %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
-    },
-    "1762317752": {
-      "message": "Expected target stack=%s to be top most but found stack=%s",
-      "level": "WARN",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RecentsAnimation.java"
-    },
-    "1764592478": {
-      "message": "reparent: moving app token=%s to task=%d at %d",
-      "level": "INFO",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "1774661765": {
       "message": "Devices still not ready after waiting %d milliseconds before attempting to detect safe mode.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1814552834": {
-      "message": "performLayout: App token exiting now removed %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
-    "1836306327": {
-      "message": "Skipping set freeze of %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/ActivityRecord.java"
-    },
-    "1865125884": {
-      "message": "finishScreenTurningOn: mAwake=%b, mScreenOnEarly=%b, mScreenOnFully=%b, mKeyguardDrawComplete=%b, mWindowManagerDrawComplete=%b",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/DisplayPolicy.java"
-    },
-    "1865246212": {
-      "message": "\tapp=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
     "1866772666": {
       "message": "SAFE MODE not enabled",
       "level": "INFO",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1878395049": {
-      "message": "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s surfaceInsets=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "1883987026": {
-      "message": "removeAppToken make exiting: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "1891501279": {
-      "message": "cancelAnimation(): reason=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "1921821199": {
-      "message": "Preserving %s until the new one is added",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "1947239194": {
-      "message": "Deferring rotation, still finishing previous rotation",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
-    "1964565370": {
-      "message": "Starting remote animation",
-      "level": "INFO",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
-    "1984470582": {
-      "message": "Creating TaskScreenshotAnimatable: task: %s width: %d height: %d",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/TaskScreenshotAnimatable.java"
-    },
-    "1984738415": {
-      "message": "Now animating app in place %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
-    "1984782949": {
-      "message": ">>> OPEN TRANSACTION animate",
-      "level": "INFO",
-      "group": "WM_SHOW_TRANSACTIONS",
-      "at": "com\/android\/server\/wm\/WindowAnimator.java"
-    },
-    "1993685727": {
-      "message": "Setting mOrientationChangeComplete=true because wtoken %s numInteresting=%d numDrawn=%d",
-      "level": "INFO",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "2016061474": {
-      "message": "Prepare app transition: transit=%s %s alwaysKeepCurrent=%b displayId=%d Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransition.java"
-    },
-    "2018454757": {
-      "message": "WS.removeImmediately: %s Already removed...",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "2028163120": {
-      "message": "applyAnimation: anim=%s nextAppTransition=ANIM_SCALE_UP transit=%s isEntrance=%s Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppTransition.java"
-    },
-    "2034780299": {
-      "message": "CHECK_IF_BOOT_ANIMATION_FINISHED:",
-      "level": "INFO",
-      "group": "WM_DEBUG_BOOT",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "2045641491": {
-      "message": "Checking %d opening apps (frozen=%b timeout=%b)...",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
-    "2054958632": {
-      "message": "Schedule remove starting %s startingWindow=%s startingView=%s Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "2057434754": {
-      "message": "\tvisible=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java"
-    },
-    "2076259606": {
-      "message": "Finish starting %s: first real window is shown, no animation",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "2083556954": {
-      "message": "Set mOrientationChanging of %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
     "2086878461": {
       "message": "Could not send command %s with parameters %s. %s",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "2088592090": {
-      "message": "handleNotObscuredLocked: %s was holding screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_KEEP_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
-    },
-    "2096635066": {
-      "message": "Acquiring screen wakelock due to %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_KEEP_SCREEN_ON",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
-    "2114149926": {
-      "message": "Not removing %s because app died while it's visible",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/WindowState.java"
-    },
-    "2128604122": {
-      "message": "findFocusedWindow: No focusable windows.",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
-    "2128917433": {
-      "message": "onProposedRotationChanged, rotation=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
-    "2137411379": {
-      "message": "applyAnimation: anim=%s animAttr=0x%x transit=%s isEntrance=%b Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppTransition.java"
     }
   },
   "groups": {
     "TEST_GROUP": {
       "tag": "WindowManagetProtoLogTest"
     },
-    "WM_DEBUG_ADD_REMOVE": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_APP_TRANSITIONS": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_APP_TRANSITIONS_ANIM": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_BOOT": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_DRAW": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_FOCUS": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_FOCUS_LIGHT": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_KEEP_SCREEN_ON": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_ORIENTATION": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_RECENTS_ANIMATIONS": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_REMOTE_ANIMATIONS": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_RESIZE": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_SCREEN_ON": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_STARTING_WINDOW": {
-      "tag": "WindowManager"
-    },
-    "WM_DEBUG_WINDOW_MOVEMENT": {
-      "tag": "WindowManager"
-    },
     "WM_ERROR": {
       "tag": "WindowManager"
-    },
-    "WM_SHOW_SURFACE_ALLOC": {
-      "tag": "WindowManager"
-    },
-    "WM_SHOW_TRANSACTIONS": {
-      "tag": "WindowManager"
     }
   }
 }
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 454dceb..4226e08 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -83,8 +83,8 @@
 
 ################################
 # Copies the font configuration file into system/etc for the product as fonts.xml.
-# In the case where $(ADDITIONAL_FONTS_FILE) is defined, the content of $(ADDITIONAL_FONTS_FILE)
-# is added to the $(AOSP_FONTS_FILE).
+# Additional fonts should be installed to /product/fonts/ alongside a corresponding
+# fonts_customiztion.xml in /product/etc/
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := fonts.xml
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 4471017..d900a42 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -1359,9 +1359,44 @@
      * Specifies the known formats a bitmap can be compressed into
      */
     public enum CompressFormat {
-        JPEG    (0),
-        PNG     (1),
-        WEBP    (2);
+        /**
+         * Compress to the JPEG format. {@code quality} of {@code 0} means
+         * compress for the smallest size. {@code 100} means compress for max
+         * visual quality.
+         */
+        JPEG          (0),
+        /**
+         * Compress to the PNG format. PNG is lossless, so {@code quality} is
+         * ignored.
+         */
+        PNG           (1),
+        /**
+         * Compress to the WEBP format. {@code quality} of {@code 0} means
+         * compress for the smallest size. {@code 100} means compress for max
+         * visual quality. As of {@link android.os.Build.VERSION_CODES#Q}, a
+         * value of {@code 100} results in a file in the lossless WEBP format.
+         * Otherwise the file will be in the lossy WEBP format.
+         *
+         * @deprecated in favor of the more explicit
+         *             {@link CompressFormat#WEBP_LOSSY} and
+         *             {@link CompressFormat#WEBP_LOSSLESS}.
+         */
+        @Deprecated
+        WEBP          (2),
+        /**
+         * Compress to the WEBP lossy format. {@code quality} of {@code 0} means
+         * compress for the smallest size. {@code 100} means compress for max
+         * visual quality.
+         */
+        WEBP_LOSSY    (3),
+        /**
+         * Compress to the WEBP lossless format. {@code quality} refers to how
+         * much effort to put into compression. A value of {@code 0} means to
+         * compress quickly, resulting in a relatively large file size.
+         * {@code 100} means to spend more time compressing, resulting in a
+         * smaller file.
+         */
+        WEBP_LOSSLESS (4);
 
         CompressFormat(int nativeInt) {
             this.nativeInt = nativeInt;
@@ -1385,10 +1420,8 @@
      * pixels).
      *
      * @param format   The format of the compressed image
-     * @param quality  Hint to the compressor, 0-100. 0 meaning compress for
-     *                 small size, 100 meaning compress for max quality. Some
-     *                 formats, like PNG which is lossless, will ignore the
-     *                 quality setting
+     * @param quality  Hint to the compressor, 0-100. The value is interpreted
+     *                 differently depending on the {@link CompressFormat}.
      * @param stream   The outputstream to write the compressed data.
      * @return true if successfully compressed to the specified stream.
      */
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index 9c4b5e8..06d4fbd 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -1380,9 +1380,9 @@
      */
     @NonNull
     static ColorSpace get(@IntRange(from = MIN_ID, to = MAX_ID) int index) {
-        if (index < 0 || index >= Named.values().length) {
+        if (index < 0 || index >= sNamedColorSpaces.length) {
             throw new IllegalArgumentException("Invalid ID, must be in the range [0.." +
-                    Named.values().length + ")");
+                    sNamedColorSpaces.length + ")");
         }
         return sNamedColorSpaces[index];
     }
diff --git a/graphics/java/android/graphics/pdf/TEST_MAPPING b/graphics/java/android/graphics/pdf/TEST_MAPPING
new file mode 100644
index 0000000..d763598
--- /dev/null
+++ b/graphics/java/android/graphics/pdf/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsPdfTestCases"
+    }
+  ]
+}
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index bf23634..254456c 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -350,7 +350,7 @@
      * access manually.
      */
     public static final String KEY_ALIAS_SELECTION_DENIED =
-            "alias-selection-denied-ef829e15-210a-409d-96c9-ee684fc41972";
+            "android:alias-selection-denied";
 
     /**
      * Returns an {@code Intent} that can be used for credential
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index a34a6c0..4f52a88 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -167,8 +167,9 @@
         },
     },
     data: [
-      "tests/data/**/*.apk",
-      "tests/data/**/*.arsc",
+        "tests/data/**/*.apk",
+        "tests/data/**/*.arsc",
+        "tests/data/**/*.idmap",
     ],
     test_suites: ["device-tests"],
 }
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index b309621..16dbbf6 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -45,7 +45,7 @@
                      time_t last_mod_time,
                      bool for_loader)
     : zip_handle_(unmanaged_handle, ::CloseArchive), path_(path), last_mod_time_(last_mod_time),
-      for_loader(for_loader) {
+      for_loader_(for_loader) {
 }
 
 std::unique_ptr<const ApkAssets> ApkAssets::Load(const std::string& path, bool system,
@@ -75,7 +75,7 @@
     return {};
   }
   return LoadImpl({} /*fd*/, loaded_idmap->OverlayApkPath(), std::move(idmap_asset),
-                  std::move(loaded_idmap), system, false /*load_as_shared_library*/);
+                  std::move(loaded_idmap), system, true /*load_as_shared_library*/);
 }
 
 std::unique_ptr<const ApkAssets> ApkAssets::LoadFromFd(unique_fd fd,
@@ -165,12 +165,14 @@
 
   // Must retain ownership of the IDMAP Asset so that all pointers to its mmapped data remain valid.
   loaded_apk->idmap_asset_ = std::move(idmap_asset);
+  loaded_apk->loaded_idmap_ = std::move(loaded_idmap);
 
   const StringPiece data(
       reinterpret_cast<const char*>(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/)),
       loaded_apk->resources_asset_->getLength());
   loaded_apk->loaded_arsc_ =
-      LoadedArsc::Load(data, loaded_idmap.get(), system, load_as_shared_library, for_loader);
+      LoadedArsc::Load(data, loaded_apk->loaded_idmap_.get(), system, load_as_shared_library,
+                       for_loader);
   if (loaded_apk->loaded_arsc_ == nullptr) {
     LOG(ERROR) << "Failed to load '" << kResourcesArsc << "' in APK '" << path << "'.";
     return {};
@@ -319,7 +321,7 @@
 
 bool ApkAssets::IsUpToDate() const {
   // Loaders are invalidated by the app, not the system, so assume up to date
-  if (for_loader) {
+  if (for_loader_) {
     return true;
   }
 
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index e914f37..ca4143f 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -25,6 +25,7 @@
 
 #include "android-base/logging.h"
 #include "android-base/stringprintf.h"
+#include "androidfw/ResourceUtils.h"
 #include "androidfw/Util.h"
 #include "utils/ByteOrder.h"
 #include "utils/Trace.h"
@@ -35,15 +36,13 @@
 #endif
 #endif
 
-#include "androidfw/ResourceUtils.h"
-
 namespace android {
 
 struct FindEntryResult {
   // A pointer to the resource table entry for this resource.
   // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
   // a ResTable_map_entry and processed as a bag/map.
-  const ResTable_entry* entry;
+  ResTable_entry_handle entry;
 
   // The configuration for which the resulting entry was defined. This is already swapped to host
   // endianness.
@@ -55,6 +54,9 @@
   // The dynamic package ID map for the package from which this resource came from.
   const DynamicRefTable* dynamic_ref_table;
 
+  // The package name of the resource.
+  const std::string* package_name;
+
   // The string pool reference to the type's name. This uses a different string pool than
   // the global string pool, but this is hidden from the caller.
   StringPoolRef type_string_ref;
@@ -83,11 +85,15 @@
   package_groups_.clear();
   package_ids_.fill(0xff);
 
+  // A mapping from apk assets path to the runtime package id of its first loaded package.
+  std::unordered_map<std::string, uint8_t> apk_assets_package_ids;
+
   // 0x01 is reserved for the android package.
   int next_package_id = 0x02;
   const size_t apk_assets_count = apk_assets_.size();
   for (size_t i = 0; i < apk_assets_count; i++) {
-    const LoadedArsc* loaded_arsc = apk_assets_[i]->GetLoadedArsc();
+    const ApkAssets* apk_assets = apk_assets_[i];
+    const LoadedArsc* loaded_arsc = apk_assets->GetLoadedArsc();
 
     for (const std::unique_ptr<const LoadedPackage>& package : loaded_arsc->GetPackages()) {
       // Get the package ID or assign one if a shared library.
@@ -103,9 +109,37 @@
       if (idx == 0xff) {
         package_ids_[package_id] = idx = static_cast<uint8_t>(package_groups_.size());
         package_groups_.push_back({});
-        DynamicRefTable& ref_table = package_groups_.back().dynamic_ref_table;
-        ref_table.mAssignedPackageId = package_id;
-        ref_table.mAppAsLib = package->IsDynamic() && package->GetPackageId() == 0x7f;
+
+        if (apk_assets->IsOverlay()) {
+          // The target package must precede the overlay package in the apk assets paths in order
+          // to take effect.
+          const auto& loaded_idmap = apk_assets->GetLoadedIdmap();
+          auto target_package_iter = apk_assets_package_ids.find(loaded_idmap->TargetApkPath());
+          if (target_package_iter != apk_assets_package_ids.end()) {
+            const uint8_t target_package_id = target_package_iter->second;
+            const uint8_t target_idx = package_ids_[target_package_id];
+            CHECK(target_idx != 0xff) << "overlay added to apk_assets_package_ids but does not"
+                                      << " have an assigned package group";
+
+            PackageGroup& target_package_group = package_groups_[target_idx];
+
+            // Create a special dynamic reference table for the overlay to rewite references to
+            // overlay resources as references to the target resources they overlay.
+            auto overlay_table = std::make_shared<OverlayDynamicRefTable>(
+                loaded_idmap->GetOverlayDynamicRefTable(target_package_id));
+            package_groups_.back().dynamic_ref_table = overlay_table;
+
+            // Add the overlay resource map to the target package's set of overlays.
+            target_package_group.overlays_.push_back(
+                ConfiguredOverlay{loaded_idmap->GetTargetResourcesMap(target_package_id,
+                                                                      overlay_table.get()),
+                                  static_cast<ApkAssetsCookie>(i)});
+          }
+        }
+
+        DynamicRefTable* ref_table = package_groups_.back().dynamic_ref_table.get();
+        ref_table->mAssignedPackageId = package_id;
+        ref_table->mAppAsLib = package->IsDynamic() && package->GetPackageId() == 0x7f;
       }
       PackageGroup* package_group = &package_groups_[idx];
 
@@ -116,9 +150,11 @@
       // Add the package name -> build time ID mappings.
       for (const DynamicPackageEntry& entry : package->GetDynamicPackageMap()) {
         String16 package_name(entry.package_name.c_str(), entry.package_name.size());
-        package_group->dynamic_ref_table.mEntries.replaceValueFor(
+        package_group->dynamic_ref_table->mEntries.replaceValueFor(
             package_name, static_cast<uint8_t>(entry.package_id));
       }
+
+      apk_assets_package_ids.insert(std::make_pair(apk_assets->GetPath(), package_id));
     }
   }
 
@@ -127,8 +163,8 @@
   for (auto iter = package_groups_.begin(); iter != package_groups_end; ++iter) {
     const std::string& package_name = iter->packages_[0].loaded_package_->GetPackageName();
     for (auto iter2 = package_groups_.begin(); iter2 != package_groups_end; ++iter2) {
-      iter2->dynamic_ref_table.addMapping(String16(package_name.c_str(), package_name.size()),
-                                          iter->dynamic_ref_table.mAssignedPackageId);
+      iter2->dynamic_ref_table->addMapping(String16(package_name.c_str(), package_name.size()),
+                                           iter->dynamic_ref_table->mAssignedPackageId);
     }
   }
 }
@@ -161,13 +197,13 @@
                           (loaded_package->IsDynamic() ? " dynamic" : ""));
     }
     LOG(INFO) << base::StringPrintf("PG (%02x): ",
-                                    package_group.dynamic_ref_table.mAssignedPackageId)
+                                    package_group.dynamic_ref_table->mAssignedPackageId)
               << list;
 
     for (size_t i = 0; i < 256; i++) {
-      if (package_group.dynamic_ref_table.mLookupTable[i] != 0) {
+      if (package_group.dynamic_ref_table->mLookupTable[i] != 0) {
         LOG(INFO) << base::StringPrintf("    e[0x%02x] -> 0x%02x", (uint8_t) i,
-                                        package_group.dynamic_ref_table.mLookupTable[i]);
+                                        package_group.dynamic_ref_table->mLookupTable[i]);
       }
     }
   }
@@ -189,14 +225,15 @@
   if (idx == 0xff) {
     return nullptr;
   }
-  return &package_groups_[idx].dynamic_ref_table;
+  return package_groups_[idx].dynamic_ref_table.get();
 }
 
-const DynamicRefTable* AssetManager2::GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const {
+std::shared_ptr<const DynamicRefTable> AssetManager2::GetDynamicRefTableForCookie(
+    ApkAssetsCookie cookie) const {
   for (const PackageGroup& package_group : package_groups_) {
     for (const ApkAssetsCookie& package_cookie : package_group.cookies_) {
       if (package_cookie == cookie) {
-        return &package_group.dynamic_ref_table;
+        return package_group.dynamic_ref_table;
       }
     }
   }
@@ -290,21 +327,45 @@
   }
 }
 
-std::set<ResTable_config> AssetManager2::GetResourceConfigurations(bool exclude_system,
-                                                                   bool exclude_mipmap) const {
-  ATRACE_NAME("AssetManager::GetResourceConfigurations");
-  std::set<ResTable_config> configurations;
+std::set<std::string> AssetManager2::GetNonSystemOverlayPaths() const {
+  std::set<std::string> non_system_overlays;
   for (const PackageGroup& package_group : package_groups_) {
     bool found_system_package = false;
     for (const ConfiguredPackage& package : package_group.packages_) {
-      if (exclude_system && package.loaded_package_->IsSystem()) {
+      if (package.loaded_package_->IsSystem()) {
         found_system_package = true;
+        break;
+      }
+    }
+
+    if (!found_system_package) {
+      for (const ConfiguredOverlay& overlay : package_group.overlays_) {
+        non_system_overlays.insert(apk_assets_[overlay.cookie]->GetPath());
+      }
+    }
+  }
+
+  return non_system_overlays;
+}
+
+std::set<ResTable_config> AssetManager2::GetResourceConfigurations(bool exclude_system,
+                                                                   bool exclude_mipmap) const {
+  ATRACE_NAME("AssetManager::GetResourceConfigurations");
+  const auto non_system_overlays =
+      (exclude_system) ? GetNonSystemOverlayPaths() : std::set<std::string>();
+
+  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;
       }
 
-      if (exclude_system && package.loaded_package_->IsOverlay() && found_system_package) {
-        // Overlays must appear after the target package to take effect. Any overlay found in the
-        // same package as a system package is able to overlay system resources.
+      auto apk_assets = apk_assets_[package_group.cookies_[i]];
+      if (exclude_system && apk_assets->IsOverlay()
+          && non_system_overlays.find(apk_assets->GetPath()) == non_system_overlays.end()) {
+        // Exclude overlays that target system resources.
         continue;
       }
 
@@ -318,17 +379,20 @@
                                                         bool merge_equivalent_languages) const {
   ATRACE_NAME("AssetManager::GetResourceLocales");
   std::set<std::string> locales;
+  const auto non_system_overlays =
+      (exclude_system) ? GetNonSystemOverlayPaths() : std::set<std::string>();
+
   for (const PackageGroup& package_group : package_groups_) {
-    bool found_system_package = false;
-    for (const ConfiguredPackage& package : package_group.packages_) {
+    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()) {
-        found_system_package = true;
         continue;
       }
 
-      if (exclude_system && package.loaded_package_->IsOverlay() && found_system_package) {
-        // Overlays must appear after the target package to take effect. Any overlay found in the
-        // same package as a system package is able to overlay system resources.
+      auto apk_assets = apk_assets_[package_group.cookies_[i]];
+      if (exclude_system && apk_assets->IsOverlay()
+          && non_system_overlays.find(apk_assets->GetPath()) == non_system_overlays.end()) {
+        // Exclude overlays that target system resources.
         continue;
       }
 
@@ -424,6 +488,12 @@
                                          bool /*stop_at_first_match*/,
                                          bool ignore_configuration,
                                          FindEntryResult* out_entry) const {
+  if (resource_resolution_logging_enabled_) {
+    // Clear the last logged resource resolution.
+    ResetResourceResolution();
+    last_resolution_.resid = resid;
+  }
+
   // Might use this if density_override != 0.
   ResTable_config density_override_config;
 
@@ -435,6 +505,7 @@
     desired_config = &density_override_config;
   }
 
+  // Retrieve the package group from the package id of the resource id.
   if (!is_valid_resid(resid)) {
     LOG(ERROR) << base::StringPrintf("Invalid ID 0x%08x.", resid);
     return kInvalidCookie;
@@ -443,8 +514,7 @@
   const uint32_t package_id = get_package_id(resid);
   const uint8_t type_idx = get_type_id(resid) - 1;
   const uint16_t entry_idx = get_entry_id(resid);
-
-  const uint8_t package_idx = package_ids_[package_id];
+  uint8_t package_idx = package_ids_[package_id];
   if (package_idx == 0xff) {
     ANDROID_LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.",
                                              package_id, resid);
@@ -452,8 +522,71 @@
   }
 
   const PackageGroup& package_group = package_groups_[package_idx];
-  const size_t package_count = package_group.packages_.size();
+  ApkAssetsCookie cookie = FindEntryInternal(package_group, type_idx, entry_idx, *desired_config,
+                                             false /* stop_at_first_match */,
+                                             ignore_configuration, out_entry);
+  if (UNLIKELY(cookie == kInvalidCookie)) {
+    return kInvalidCookie;
+  }
 
+  if (!apk_assets_[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.IsTableEntry()) {
+        // The target resource is overlaid by an inline value not represented by a resource.
+        out_entry->entry = overlay_entry.GetTableEntry();
+        out_entry->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
+        cookie = id_map.cookie;
+        continue;
+      }
+
+      FindEntryResult overlay_result;
+      ApkAssetsCookie overlay_cookie = FindEntry(overlay_entry.GetResourceId(), density_override,
+                                                 false /* stop_at_first_match */,
+                                                 ignore_configuration, &overlay_result);
+      if (UNLIKELY(overlay_cookie == kInvalidCookie)) {
+        continue;
+      }
+
+      if (!overlay_result.config.isBetterThan(out_entry->config, desired_config)
+          && overlay_result.config.compare(out_entry->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;
+      }
+
+      cookie = overlay_cookie;
+      out_entry->entry = std::move(overlay_result.entry);
+      out_entry->config = overlay_result.config;
+      out_entry->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
+      if (resource_resolution_logging_enabled_) {
+        last_resolution_.steps.push_back(
+            Resolution::Step{Resolution::Step::Type::OVERLAID, overlay_result.config.toString(),
+                             &package_group.packages_[0].loaded_package_->GetPackageName()});
+      }
+    }
+  }
+
+  if (resource_resolution_logging_enabled_) {
+    last_resolution_.cookie = cookie;
+    last_resolution_.type_string_ref = out_entry->type_string_ref;
+    last_resolution_.entry_string_ref = out_entry->entry_string_ref;
+  }
+
+  return cookie;
+}
+
+ApkAssetsCookie AssetManager2::FindEntryInternal(const PackageGroup& package_group,
+                                                 uint8_t type_idx, uint16_t entry_idx,
+                                                 const ResTable_config& desired_config,
+                                                 bool /*stop_at_first_match*/,
+                                                 bool ignore_configuration,
+                                                 FindEntryResult* out_entry) const {
   ApkAssetsCookie best_cookie = kInvalidCookie;
   const LoadedPackage* best_package = nullptr;
   const ResTable_type* best_type = nullptr;
@@ -462,13 +595,14 @@
   uint32_t best_offset = 0u;
   uint32_t type_flags = 0u;
 
-  Resolution::Step::Type resolution_type;
+  Resolution::Step::Type resolution_type = Resolution::Step::Type::NO_ENTRY;
   std::vector<Resolution::Step> resolution_steps;
 
   // If desired_config is the same as the set configuration, then we can use our filtered list
   // and we don't need to match the configurations, since they already matched.
-  const bool use_fast_path = !ignore_configuration && desired_config == &configuration_;
+  const bool use_fast_path = !ignore_configuration && &desired_config == &configuration_;
 
+  const size_t package_count = package_group.packages_.size();
   for (size_t pi = 0; pi < package_count; pi++) {
     const ConfiguredPackage& loaded_package_impl = package_group.packages_[pi];
     const LoadedPackage* loaded_package = loaded_package_impl.loaded_package_;
@@ -481,24 +615,10 @@
       continue;
     }
 
-    uint16_t local_entry_idx = entry_idx;
-
-    // If there is an IDMAP supplied with this package, translate the entry ID.
-    if (type_spec->idmap_entries != nullptr) {
-      if (!LoadedIdmap::Lookup(type_spec->idmap_entries, local_entry_idx, &local_entry_idx)) {
-        // There is no mapping, so the resource is not meant to be in this overlay package.
-        continue;
-      }
-    }
-
-    type_flags |= type_spec->GetFlagsForEntryIndex(local_entry_idx);
-
-
     // If the package is an overlay or custom loader,
     // then even configurations that are the same MUST be chosen.
-    const bool package_is_overlay = loaded_package->IsOverlay();
     const bool package_is_loader = loaded_package->IsCustomLoader();
-    const bool should_overlay = package_is_overlay || package_is_loader;
+    type_flags |= type_spec->GetFlagsForEntryIndex(entry_idx);
 
     if (use_fast_path) {
       const FilteredConfigGroup& filtered_group = loaded_package_impl.filtered_configs_[type_idx];
@@ -511,25 +631,15 @@
         // configurations that do NOT match have been filtered-out.
         if (best_config == nullptr) {
           resolution_type = Resolution::Step::Type::INITIAL;
-        } else if (this_config.isBetterThan(*best_config, desired_config)) {
-          if (package_is_loader) {
-            resolution_type = Resolution::Step::Type::BETTER_MATCH_LOADER;
-          } else {
-            resolution_type = Resolution::Step::Type::BETTER_MATCH;
-          }
-        } else if (should_overlay && this_config.compare(*best_config) == 0) {
-          if (package_is_loader) {
-            resolution_type = Resolution::Step::Type::OVERLAID_LOADER;
-          } else if (package_is_overlay) {
-            resolution_type = Resolution::Step::Type::OVERLAID;
-          }
+        } else if (this_config.isBetterThan(*best_config, &desired_config)) {
+          resolution_type = (package_is_loader) ? Resolution::Step::Type::BETTER_MATCH_LOADER
+                                                : Resolution::Step::Type::BETTER_MATCH;
+        } else if (package_is_loader && this_config.compare(*best_config) == 0) {
+          resolution_type = Resolution::Step::Type::OVERLAID_LOADER;
         } else {
           if (resource_resolution_logging_enabled_) {
-            if (package_is_loader) {
-              resolution_type = Resolution::Step::Type::SKIPPED_LOADER;
-            } else {
-              resolution_type = Resolution::Step::Type::SKIPPED;
-            }
+            resolution_type = (package_is_loader) ? Resolution::Step::Type::SKIPPED_LOADER
+                                                  : Resolution::Step::Type::SKIPPED;
             resolution_steps.push_back(Resolution::Step{resolution_type,
                                                         this_config.toString(),
                                                         &loaded_package->GetPackageName()});
@@ -540,7 +650,7 @@
         // The configuration matches and is better than the previous selection.
         // Find the entry value if it exists for this configuration.
         const ResTable_type* type = filtered_group.types[i];
-        const uint32_t offset = LoadedPackage::GetEntryOffset(type, local_entry_idx);
+        const uint32_t offset = LoadedPackage::GetEntryOffset(type, entry_idx);
         if (offset == ResTable_type::NO_ENTRY) {
           if (resource_resolution_logging_enabled_) {
             if (package_is_loader) {
@@ -548,7 +658,7 @@
             } else {
               resolution_type = Resolution::Step::Type::NO_ENTRY;
             }
-            resolution_steps.push_back(Resolution::Step{Resolution::Step::Type::NO_ENTRY,
+            resolution_steps.push_back(Resolution::Step{resolution_type,
                                                         this_config.toString(),
                                                         &loaded_package->GetPackageName()});
           }
@@ -562,9 +672,9 @@
         best_offset = offset;
 
         if (resource_resolution_logging_enabled_) {
-          resolution_steps.push_back(Resolution::Step{resolution_type,
-                                                      this_config.toString(),
-                                                      &loaded_package->GetPackageName()});
+          last_resolution_.steps.push_back(Resolution::Step{resolution_type,
+                                                            this_config.toString(),
+                                                            &loaded_package->GetPackageName()});
         }
       }
     } else {
@@ -579,24 +689,17 @@
 
         if (!ignore_configuration) {
           this_config.copyFromDtoH((*iter)->config);
-          if (!this_config.match(*desired_config)) {
+          if (!this_config.match(desired_config)) {
             continue;
           }
 
           if (best_config == nullptr) {
             resolution_type = Resolution::Step::Type::INITIAL;
-          } else if (this_config.isBetterThan(*best_config, desired_config)) {
-            if (package_is_loader) {
-              resolution_type = Resolution::Step::Type::BETTER_MATCH_LOADER;
-            } else {
-              resolution_type = Resolution::Step::Type::BETTER_MATCH;
-            }
-          } else if (should_overlay && this_config.compare(*best_config) == 0) {
-            if (package_is_overlay) {
-              resolution_type = Resolution::Step::Type::OVERLAID;
-            } else if (package_is_loader) {
-              resolution_type = Resolution::Step::Type::OVERLAID_LOADER;
-            }
+          } else if (this_config.isBetterThan(*best_config, &desired_config)) {
+            resolution_type = (package_is_loader) ? Resolution::Step::Type::BETTER_MATCH_LOADER
+                                                  : Resolution::Step::Type::BETTER_MATCH;
+          } else if (package_is_loader && this_config.compare(*best_config) == 0) {
+            resolution_type = Resolution::Step::Type::OVERLAID_LOADER;
           } else {
             continue;
           }
@@ -604,7 +707,7 @@
 
         // The configuration matches and is better than the previous selection.
         // Find the entry value if it exists for this configuration.
-        const uint32_t offset = LoadedPackage::GetEntryOffset(*iter, local_entry_idx);
+        const uint32_t offset = LoadedPackage::GetEntryOffset(*iter, entry_idx);
         if (offset == ResTable_type::NO_ENTRY) {
           continue;
         }
@@ -622,9 +725,9 @@
         }
 
         if (resource_resolution_logging_enabled_) {
-          resolution_steps.push_back(Resolution::Step{resolution_type,
-                                                      this_config.toString(),
-                                                      &loaded_package->GetPackageName()});
+          last_resolution_.steps.push_back(Resolution::Step{resolution_type,
+                                                            this_config.toString(),
+                                                            &loaded_package->GetPackageName()});
         }
       }
     }
@@ -639,38 +742,30 @@
     return kInvalidCookie;
   }
 
-  out_entry->entry = best_entry;
+  out_entry->entry = ResTable_entry_handle::unmanaged(best_entry);
   out_entry->config = *best_config;
   out_entry->type_flags = type_flags;
+  out_entry->package_name = &best_package->GetPackageName();
   out_entry->type_string_ref = StringPoolRef(best_package->GetTypeStringPool(), best_type->id - 1);
   out_entry->entry_string_ref =
-      StringPoolRef(best_package->GetKeyStringPool(), best_entry->key.index);
-  out_entry->dynamic_ref_table = &package_group.dynamic_ref_table;
-
-  if (resource_resolution_logging_enabled_) {
-    last_resolution.resid = resid;
-    last_resolution.cookie = best_cookie;
-    last_resolution.steps = resolution_steps;
-
-    // Cache only the type/entry refs since that's all that's needed to build name
-    last_resolution.type_string_ref =
-        StringPoolRef(best_package->GetTypeStringPool(), best_type->id - 1);
-    last_resolution.entry_string_ref =
-        StringPoolRef(best_package->GetKeyStringPool(), best_entry->key.index);
-  }
+          StringPoolRef(best_package->GetKeyStringPool(), best_entry->key.index);
+  out_entry->dynamic_ref_table = package_group.dynamic_ref_table.get();
 
   return best_cookie;
 }
 
+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();
+}
+
 void AssetManager2::SetResourceResolutionLoggingEnabled(bool enabled) {
   resource_resolution_logging_enabled_ = enabled;
-
   if (!enabled) {
-    last_resolution.cookie = kInvalidCookie;
-    last_resolution.resid = 0;
-    last_resolution.steps.clear();
-    last_resolution.type_string_ref = StringPoolRef();
-    last_resolution.entry_string_ref = StringPoolRef();
+    ResetResourceResolution();
   }
 }
 
@@ -680,24 +775,24 @@
     return std::string();
   }
 
-  auto cookie = last_resolution.cookie;
+  auto cookie = last_resolution_.cookie;
   if (cookie == kInvalidCookie) {
     LOG(ERROR) << "AssetManager hasn't resolved a resource to read resolution path.";
     return std::string();
   }
 
-  uint32_t resid = last_resolution.resid;
-  std::vector<Resolution::Step>& steps = last_resolution.steps;
+  uint32_t resid = last_resolution_.resid;
+  std::vector<Resolution::Step>& steps = last_resolution_.steps;
 
   ResourceName resource_name;
   std::string resource_name_string;
 
   const LoadedPackage* package =
-      apk_assets_[cookie]->GetLoadedArsc()->GetPackageById(get_package_id(resid));
+          apk_assets_[cookie]->GetLoadedArsc()->GetPackageById(get_package_id(resid));
 
   if (package != nullptr) {
-    ToResourceName(last_resolution.type_string_ref,
-                   last_resolution.entry_string_ref,
+    ToResourceName(last_resolution_.type_string_ref,
+                   last_resolution_.entry_string_ref,
                    package->GetPackageName(),
                    &resource_name);
     resource_name_string = ToFormattedResourceString(&resource_name);
@@ -762,25 +857,9 @@
     return false;
   }
 
-  const uint8_t package_idx = package_ids_[get_package_id(resid)];
-  if (package_idx == 0xff) {
-    LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.",
-                                     get_package_id(resid), resid);
-    return false;
-  }
-
-  const PackageGroup& package_group = package_groups_[package_idx];
-  auto cookie_iter = std::find(package_group.cookies_.begin(),
-                               package_group.cookies_.end(), cookie);
-  if (cookie_iter == package_group.cookies_.end()) {
-    return false;
-  }
-
-  long package_pos = std::distance(package_group.cookies_.begin(), cookie_iter);
-  const LoadedPackage* package = package_group.packages_[package_pos].loaded_package_;
   return ToResourceName(entry.type_string_ref,
                         entry.entry_string_ref,
-                        package->GetPackageName(),
+                        *entry.package_name,
                         out_name);
 }
 
@@ -807,7 +886,8 @@
     return kInvalidCookie;
   }
 
-  if (dtohs(entry.entry->flags) & ResTable_entry::FLAG_COMPLEX) {
+  const ResTable_entry* table_entry = *entry.entry;
+  if (dtohs(table_entry->flags) & ResTable_entry::FLAG_COMPLEX) {
     if (!may_be_bag) {
       LOG(ERROR) << base::StringPrintf("Resource %08x is a complex map type.", resid);
       return kInvalidCookie;
@@ -822,7 +902,7 @@
   }
 
   const Res_value* device_value = reinterpret_cast<const Res_value*>(
-      reinterpret_cast<const uint8_t*>(entry.entry) + dtohs(entry.entry->size));
+      reinterpret_cast<const uint8_t*>(table_entry) + dtohs(table_entry->size));
   out_value->copyFrom_dtoh(*device_value);
 
   // Convert the package ID to the runtime assigned package ID.
@@ -903,13 +983,14 @@
   // Check that the size of the entry header is at least as big as
   // the desired ResTable_map_entry. Also verify that the entry
   // was intended to be a map.
-  if (dtohs(entry.entry->size) < sizeof(ResTable_map_entry) ||
-      (dtohs(entry.entry->flags) & ResTable_entry::FLAG_COMPLEX) == 0) {
+  const ResTable_entry* table_entry = *entry.entry;
+  if (dtohs(table_entry->size) < sizeof(ResTable_map_entry) ||
+      (dtohs(table_entry->flags) & ResTable_entry::FLAG_COMPLEX) == 0) {
     // Not a bag, nothing to do.
     return nullptr;
   }
 
-  const ResTable_map_entry* map = reinterpret_cast<const ResTable_map_entry*>(entry.entry);
+  const ResTable_map_entry* map = reinterpret_cast<const ResTable_map_entry*>(table_entry);
   const ResTable_map* map_entry =
       reinterpret_cast<const ResTable_map*>(reinterpret_cast<const uint8_t*>(map) + map->size);
   const ResTable_map* const map_entry_end = map_entry + dtohl(map->count);
@@ -1134,7 +1215,7 @@
       }
 
       if (resid != 0u) {
-        return fix_package_id(resid, package_group.dynamic_ref_table.mAssignedPackageId);
+        return fix_package_id(resid, package_group.dynamic_ref_table->mAssignedPackageId);
       }
     }
   }
@@ -1191,7 +1272,7 @@
   for (auto& package_group : package_groups_) {
     for (auto& package2 : package_group.packages_) {
       if (package2.loaded_package_ == package) {
-        return package_group.dynamic_ref_table.mAssignedPackageId;
+        return package_group.dynamic_ref_table->mAssignedPackageId;
       }
     }
   }
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index 7c1ee5c..2b69c92 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -20,6 +20,8 @@
 
 #include "android-base/logging.h"
 #include "android-base/stringprintf.h"
+#include "androidfw/ResourceTypes.h"
+#include "androidfw/Util.h"
 #include "utils/ByteOrder.h"
 #include "utils/Trace.h"
 
@@ -29,40 +31,124 @@
 #endif
 #endif
 
-#include "androidfw/ResourceTypes.h"
-
 using ::android::base::StringPrintf;
 
 namespace android {
 
-constexpr static inline bool is_valid_package_id(uint16_t id) {
-  return id != 0 && id <= 255;
+static bool compare_target_entries(const Idmap_target_entry &e1, const uint32_t target_id) {
+  return dtohl(e1.target_id) < target_id;
 }
 
-constexpr static inline bool is_valid_type_id(uint16_t id) {
-  // Type IDs and package IDs have the same constraints in the IDMAP.
-  return is_valid_package_id(id);
+static bool compare_overlay_entries(const Idmap_overlay_entry& e1, const uint32_t overlay_id) {
+  return dtohl(e1.overlay_id) < overlay_id;
 }
 
-bool LoadedIdmap::Lookup(const IdmapEntry_header* header, uint16_t input_entry_id,
-                         uint16_t* output_entry_id) {
-  if (input_entry_id < dtohs(header->entry_id_offset)) {
-    // After applying the offset, the entry is not present.
-    return false;
+OverlayStringPool::OverlayStringPool(const LoadedIdmap* loaded_idmap)
+                                     : data_header_(loaded_idmap->data_header_),
+                                       idmap_string_pool_(loaded_idmap->string_pool_.get()) { };
+
+OverlayStringPool::~OverlayStringPool() {
+  uninit();
+}
+
+const char16_t* OverlayStringPool::stringAt(size_t idx, size_t* outLen) const {
+  const size_t offset = dtohl(data_header_->string_pool_index_offset);
+  if (idmap_string_pool_ != nullptr && idx >= size() && idx >= offset) {
+    return idmap_string_pool_->stringAt(idx - offset, outLen);
   }
 
-  input_entry_id -= dtohs(header->entry_id_offset);
-  if (input_entry_id >= dtohs(header->entry_count)) {
-    // The entry is not present.
-    return false;
+  return ResStringPool::stringAt(idx, outLen);
+}
+
+const char* OverlayStringPool::string8At(size_t idx, size_t* outLen) const {
+  const size_t offset = dtohl(data_header_->string_pool_index_offset);
+  if (idmap_string_pool_ != nullptr && idx >= size() && idx >= offset) {
+    return idmap_string_pool_->string8At(idx - offset, outLen);
   }
 
-  uint32_t result = dtohl(header->entries[input_entry_id]);
-  if (result == 0xffffffffu) {
-    return false;
+  return ResStringPool::string8At(idx, outLen);
+}
+
+OverlayDynamicRefTable::OverlayDynamicRefTable(const Idmap_data_header* data_header,
+                                               const Idmap_overlay_entry* entries,
+                                               uint8_t target_assigned_package_id)
+    : data_header_(data_header),
+      entries_(entries),
+      target_assigned_package_id_(target_assigned_package_id) { };
+
+status_t OverlayDynamicRefTable::lookupResourceId(uint32_t* resId) const {
+  const Idmap_overlay_entry* first_entry = entries_;
+  const Idmap_overlay_entry* end_entry = entries_ + dtohl(data_header_->overlay_entry_count);
+  auto entry = std::lower_bound(first_entry, end_entry, *resId, compare_overlay_entries);
+
+  if (entry == end_entry || dtohl(entry->overlay_id) != *resId) {
+    // A mapping for the target resource id could not be found.
+    return DynamicRefTable::lookupResourceId(resId);
   }
-  *output_entry_id = static_cast<uint16_t>(result);
-  return true;
+
+  *resId = (0x00FFFFFFU & dtohl(entry->target_id))
+      | (((uint32_t) target_assigned_package_id_) << 24);
+  return NO_ERROR;
+}
+
+status_t OverlayDynamicRefTable::lookupResourceIdNoRewrite(uint32_t* resId) const {
+  return DynamicRefTable::lookupResourceId(resId);
+}
+
+IdmapResMap::IdmapResMap(const Idmap_data_header* data_header,
+                         const Idmap_target_entry* entries,
+                         uint8_t target_assigned_package_id,
+                         const OverlayDynamicRefTable* overlay_ref_table)
+    : data_header_(data_header),
+      entries_(entries),
+      target_assigned_package_id_(target_assigned_package_id),
+      overlay_ref_table_(overlay_ref_table) { };
+
+IdmapResMap::Result IdmapResMap::Lookup(uint32_t target_res_id) const {
+  if ((target_res_id >> 24) != target_assigned_package_id_) {
+    // The resource id must have the same package id as the target package.
+    return {};
+  }
+
+  // The resource ids encoded within the idmap are build-time resource ids.
+  target_res_id = (0x00FFFFFFU & target_res_id)
+      | (((uint32_t) data_header_->target_package_id) << 24);
+
+  const Idmap_target_entry* first_entry = entries_;
+  const Idmap_target_entry* end_entry = entries_ + dtohl(data_header_->target_entry_count);
+  auto entry = std::lower_bound(first_entry, end_entry, target_res_id, compare_target_entries);
+
+  if (entry == end_entry || dtohl(entry->target_id) != target_res_id) {
+    // A mapping for the target resource id could not be found.
+    return {};
+  }
+
+  // A reference should be treated as an alias of the resource. Instead of returning the table
+  // entry, return the alias resource id to look up. The alias resource might not reside within the
+  // overlay package, so the resource id must be fixed with the dynamic reference table of the
+  // overlay before returning.
+  if (entry->type == Res_value::TYPE_REFERENCE
+      || entry->type == Res_value::TYPE_DYNAMIC_REFERENCE) {
+    uint32_t overlay_resource_id = dtohl(entry->value);
+
+    // Lookup the resource without rewriting the overlay resource id back to the target resource id
+    // being looked up.
+    overlay_ref_table_->lookupResourceIdNoRewrite(&overlay_resource_id);
+    return Result(overlay_resource_id);
+  }
+
+  // Copy the type and value into the ResTable_entry structure needed by asset manager.
+  uint16_t malloc_size = sizeof(ResTable_entry) + sizeof(Res_value);
+  auto table_entry = reinterpret_cast<ResTable_entry*>(malloc(malloc_size));
+  memset(table_entry, 0, malloc_size);
+  table_entry->size = htods(sizeof(ResTable_entry));
+
+  auto table_value = reinterpret_cast<Res_value*>(reinterpret_cast<uint8_t*>(table_entry)
+      + sizeof(ResTable_entry));
+  table_value->dataType = entry->type;
+  table_value->data = entry->value;
+
+  return Result(ResTable_entry_handle::managed(table_entry));
 }
 
 static bool is_word_aligned(const void* data) {
@@ -95,24 +181,26 @@
     return false;
   }
 
-  if (!is_valid_package_id(dtohs(header->target_package_id))) {
-    LOG(ERROR) << StringPrintf("Target package ID in Idmap is invalid: 0x%02x",
-                               dtohs(header->target_package_id));
-    return false;
-  }
-
-  if (dtohs(header->type_count) > 255) {
-    LOG(ERROR) << StringPrintf("Idmap has too many type mappings (was %d, max 255)",
-                               (int)dtohs(header->type_count));
-    return false;
-  }
   return true;
 }
 
-LoadedIdmap::LoadedIdmap(const Idmap_header* header) : header_(header) {
+LoadedIdmap::LoadedIdmap(const Idmap_header* header,
+                         const Idmap_data_header* data_header,
+                         const Idmap_target_entry* target_entries,
+                         const Idmap_overlay_entry* overlay_entries,
+                         ResStringPool* string_pool) : header_(header),
+                                                       data_header_(data_header),
+                                                       target_entries_(target_entries),
+                                                       overlay_entries_(overlay_entries),
+                                                       string_pool_(string_pool) {
+
   size_t length = strnlen(reinterpret_cast<const char*>(header_->overlay_path),
                           arraysize(header_->overlay_path));
   overlay_apk_path_.assign(reinterpret_cast<const char*>(header_->overlay_path), length);
+
+  length = strnlen(reinterpret_cast<const char*>(header_->target_path),
+                          arraysize(header_->target_path));
+  target_apk_path_.assign(reinterpret_cast<const char*>(header_->target_path), length);
 }
 
 std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_data) {
@@ -121,70 +209,67 @@
     return {};
   }
 
-  const Idmap_header* header = reinterpret_cast<const Idmap_header*>(idmap_data.data());
-
-  // Can't use make_unique because LoadedImpl constructor is private.
-  std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>(new LoadedIdmap(header));
-
+  auto header = reinterpret_cast<const Idmap_header*>(idmap_data.data());
   const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(idmap_data.data()) + sizeof(*header);
   size_t data_size = idmap_data.size() - sizeof(*header);
 
-  size_t type_maps_encountered = 0u;
-  while (data_size >= sizeof(IdmapEntry_header)) {
-    if (!is_word_aligned(data_ptr)) {
-      LOG(ERROR) << "Type mapping in Idmap is not word aligned";
-      return {};
-    }
+  // Currently idmap2 can only generate one data block.
+  auto data_header = reinterpret_cast<const Idmap_data_header*>(data_ptr);
+  data_ptr += sizeof(*data_header);
+  data_size -= sizeof(*data_header);
 
-    // Validate the type IDs.
-    const IdmapEntry_header* entry_header = reinterpret_cast<const IdmapEntry_header*>(data_ptr);
-    if (!is_valid_type_id(dtohs(entry_header->target_type_id)) || !is_valid_type_id(dtohs(entry_header->overlay_type_id))) {
-      LOG(ERROR) << StringPrintf("Invalid type map (0x%02x -> 0x%02x)",
-                                 dtohs(entry_header->target_type_id),
-                                 dtohs(entry_header->overlay_type_id));
-      return {};
-    }
-
-    // Make sure there is enough space for the entries declared in the header.
-    if ((data_size - sizeof(*entry_header)) / sizeof(uint32_t) <
-        static_cast<size_t>(dtohs(entry_header->entry_count))) {
-      LOG(ERROR) << StringPrintf("Idmap too small for the number of entries (%d)",
-                                 (int)dtohs(entry_header->entry_count));
-      return {};
-    }
-
-    // Only add a non-empty overlay.
-    if (dtohs(entry_header->entry_count != 0)) {
-      loaded_idmap->type_map_[static_cast<uint8_t>(dtohs(entry_header->overlay_type_id))] =
-          entry_header;
-    }
-
-    const size_t entry_size_bytes =
-        sizeof(*entry_header) + (dtohs(entry_header->entry_count) * sizeof(uint32_t));
-    data_ptr += entry_size_bytes;
-    data_size -= entry_size_bytes;
-    type_maps_encountered++;
-  }
-
-  // Verify that we parsed all the type maps.
-  if (type_maps_encountered != static_cast<size_t>(dtohs(header->type_count))) {
-    LOG(ERROR) << "Parsed " << type_maps_encountered << " type maps but expected "
-               << (int)dtohs(header->type_count);
+  // Make sure there is enough space for the target entries declared in the header.
+  const auto target_entries = reinterpret_cast<const Idmap_target_entry*>(data_ptr);
+  if (data_size / sizeof(Idmap_target_entry) <
+      static_cast<size_t>(dtohl(data_header->target_entry_count))) {
+    LOG(ERROR) << StringPrintf("Idmap too small for the number of target entries (%d)",
+                               (int)dtohl(data_header->target_entry_count));
     return {};
   }
-  return std::move(loaded_idmap);
-}
 
-uint8_t LoadedIdmap::TargetPackageId() const {
-  return static_cast<uint8_t>(dtohs(header_->target_package_id));
-}
+  // Advance the data pointer past the target entries.
+  const size_t target_entry_size_bytes =
+      (dtohl(data_header->target_entry_count) * sizeof(Idmap_target_entry));
+  data_ptr += target_entry_size_bytes;
+  data_size -= target_entry_size_bytes;
 
-const IdmapEntry_header* LoadedIdmap::GetEntryMapForType(uint8_t type_id) const {
-  auto iter = type_map_.find(type_id);
-  if (iter != type_map_.end()) {
-    return iter->second;
+  // Make sure there is enough space for the overlay entries declared in the header.
+  const auto overlay_entries = reinterpret_cast<const Idmap_overlay_entry*>(data_ptr);
+  if (data_size / sizeof(Idmap_overlay_entry) <
+      static_cast<size_t>(dtohl(data_header->overlay_entry_count))) {
+    LOG(ERROR) << StringPrintf("Idmap too small for the number of overlay entries (%d)",
+                               (int)dtohl(data_header->overlay_entry_count));
+    return {};
   }
-  return nullptr;
+
+  // Advance the data pointer past the target entries.
+  const size_t overlay_entry_size_bytes =
+      (dtohl(data_header->overlay_entry_count) * sizeof(Idmap_overlay_entry));
+  data_ptr += overlay_entry_size_bytes;
+  data_size -= overlay_entry_size_bytes;
+
+  // Read the idmap string pool that holds the value of inline string entries.
+  if (data_size < dtohl(data_header->string_pool_length)) {
+    LOG(ERROR) << StringPrintf("Idmap too small for string pool (length %d)",
+                               (int)dtohl(data_header->string_pool_length));
+    return {};
+  }
+
+  auto idmap_string_pool = util::make_unique<ResStringPool>();
+  if (dtohl(data_header->string_pool_length) > 0) {
+    status_t err = idmap_string_pool->setTo(data_ptr, dtohl(data_header->string_pool_length));
+    if (err != NO_ERROR) {
+      LOG(ERROR) << "idmap string pool corrupt.";
+      return {};
+    }
+  }
+
+   // Can't use make_unique because LoadedImpl constructor is private.
+  std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>(
+      new LoadedIdmap(header, data_header, target_entries, overlay_entries,
+                      idmap_string_pool.release()));
+
+  return std::move(loaded_idmap);
 }
 
 }  // namespace android
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index 882dc0d..c896241 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -51,9 +51,8 @@
 // the Type structs.
 class TypeSpecPtrBuilder {
  public:
-  explicit TypeSpecPtrBuilder(const ResTable_typeSpec* header,
-                              const IdmapEntry_header* idmap_header)
-      : header_(header), idmap_header_(idmap_header) {
+  explicit TypeSpecPtrBuilder(const ResTable_typeSpec* header)
+      : header_(header) {
   }
 
   void AddType(const ResTable_type* type) {
@@ -70,7 +69,6 @@
     TypeSpec* type_spec =
         (TypeSpec*)::malloc(sizeof(TypeSpec) + (types_.size() * sizeof(ElementType)));
     type_spec->type_spec = header_;
-    type_spec->idmap_entries = idmap_header_;
     type_spec->type_count = types_.size();
     memcpy(type_spec + 1, types_.data(), types_.size() * sizeof(ElementType));
     return TypeSpecPtr(type_spec);
@@ -80,7 +78,6 @@
   DISALLOW_COPY_AND_ASSIGN(TypeSpecPtrBuilder);
 
   const ResTable_typeSpec* header_;
-  const IdmapEntry_header* idmap_header_;
   std::vector<const ResTable_type*> types_;
 };
 
@@ -400,7 +397,6 @@
 }
 
 std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
-                                                         const LoadedIdmap* loaded_idmap,
                                                          bool system,
                                                          bool load_as_shared_library,
                                                          bool for_loader) {
@@ -426,12 +422,6 @@
     loaded_package->dynamic_ = true;
   }
 
-  if (loaded_idmap != nullptr) {
-    // This is an overlay and so it needs to pretend to be the target package.
-    loaded_package->package_id_ = loaded_idmap->TargetPackageId();
-    loaded_package->overlay_ = true;
-  }
-
   if (for_loader) {
     loaded_package->custom_loader_ = true;
   }
@@ -517,16 +507,9 @@
           return {};
         }
 
-        // If this is an overlay, associate the mapping of this type to the target type
-        // from the IDMAP.
-        const IdmapEntry_header* idmap_entry_header = nullptr;
-        if (loaded_idmap != nullptr) {
-          idmap_entry_header = loaded_idmap->GetEntryMapForType(type_spec->id);
-        }
-
         std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type_spec->id - 1];
         if (builder_ptr == nullptr) {
-          builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header);
+          builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec);
           loaded_package->resource_ids_.set(type_spec->id, entry_count);
         } else {
           LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x",
@@ -687,15 +670,7 @@
       return {};
     }
 
-    // We only add the type to the package if there is no IDMAP, or if the type is
-    // overlaying something.
-    if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) {
-      // If this is an overlay, insert it at the target type ID.
-      if (type_spec_ptr->idmap_entries != nullptr) {
-        type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1;
-      }
-      loaded_package->type_specs_.editItemAt(type_idx) = std::move(type_spec_ptr);
-    }
+    loaded_package->type_specs_.editItemAt(type_idx) = std::move(type_spec_ptr);
   }
 
   return std::move(loaded_package);
@@ -709,6 +684,10 @@
     return false;
   }
 
+  if (loaded_idmap != nullptr) {
+    global_string_pool_ = util::make_unique<OverlayStringPool>(loaded_idmap);
+  }
+
   const size_t package_count = dtohl(header->packageCount);
   size_t packages_seen = 0;
 
@@ -720,9 +699,9 @@
     switch (child_chunk.type()) {
       case RES_STRING_POOL_TYPE:
         // Only use the first string pool. Ignore others.
-        if (global_string_pool_.getError() == NO_INIT) {
-          status_t err = global_string_pool_.setTo(child_chunk.header<ResStringPool_header>(),
-                                                   child_chunk.size());
+        if (global_string_pool_->getError() == NO_INIT) {
+          status_t err = global_string_pool_->setTo(child_chunk.header<ResStringPool_header>(),
+                                                    child_chunk.size());
           if (err != NO_ERROR) {
             LOG(ERROR) << "RES_STRING_POOL_TYPE corrupt.";
             return false;
@@ -741,11 +720,7 @@
         packages_seen++;
 
         std::unique_ptr<const LoadedPackage> loaded_package =
-            LoadedPackage::Load(child_chunk,
-                                loaded_idmap,
-                                system_,
-                                load_as_shared_library,
-                                for_loader);
+            LoadedPackage::Load(child_chunk, system_, load_as_shared_library, for_loader);
         if (!loaded_package) {
           return false;
         }
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 3fe2c5b..4d7e5df 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -1363,11 +1363,10 @@
                 (((const uint8_t*)tag)
                  + dtohs(tag->attributeStart)
                  + (dtohs(tag->attributeSize)*idx));
-            if (attr->typedValue.dataType != Res_value::TYPE_DYNAMIC_REFERENCE ||
-                    mTree.mDynamicRefTable == NULL) {
+            if (mTree.mDynamicRefTable == NULL ||
+                    !mTree.mDynamicRefTable->requiresLookup(&attr->typedValue)) {
                 return dtohl(attr->typedValue.data);
             }
-
             uint32_t data = dtohl(attr->typedValue.data);
             if (mTree.mDynamicRefTable->lookupResourceId(&data) == NO_ERROR) {
                 return data;
@@ -1613,10 +1612,9 @@
 
 static volatile int32_t gCount = 0;
 
-ResXMLTree::ResXMLTree(const DynamicRefTable* dynamicRefTable)
+ResXMLTree::ResXMLTree(std::shared_ptr<const DynamicRefTable> dynamicRefTable)
     : ResXMLParser(*this)
-    , mDynamicRefTable((dynamicRefTable != nullptr) ? dynamicRefTable->clone()
-                                                    : std::unique_ptr<DynamicRefTable>(nullptr))
+    , mDynamicRefTable(std::move(dynamicRefTable))
     , mError(NO_INIT), mOwnedData(NULL)
 {
     if (kDebugResXMLTree) {
@@ -1627,7 +1625,7 @@
 
 ResXMLTree::ResXMLTree()
     : ResXMLParser(*this)
-    , mDynamicRefTable(std::unique_ptr<DynamicRefTable>(nullptr))
+    , mDynamicRefTable(nullptr)
     , mError(NO_INIT), mOwnedData(NULL)
 {
     if (kDebugResXMLTree) {
@@ -4789,7 +4787,7 @@
         packageGroup->clearBagCache();
 
         // Find which configurations match the set of parameters. This allows for a much
-        // faster lookup in getEntry() if the set of values is narrowed down.
+        // faster lookup in Lookup() if the set of values is narrowed down.
         for (size_t t = 0; t < packageGroup->types.size(); t++) {
             if (packageGroup->types[t].isEmpty()) {
                 continue;
@@ -6897,13 +6895,6 @@
     mLookupTable[SYS_PACKAGE_ID] = SYS_PACKAGE_ID;
 }
 
-std::unique_ptr<DynamicRefTable> DynamicRefTable::clone() const {
-  std::unique_ptr<DynamicRefTable> clone = std::unique_ptr<DynamicRefTable>(
-      new DynamicRefTable(mAssignedPackageId, mAppAsLib));
-  clone->addMappings(*this);
-  return clone;
-}
-
 status_t DynamicRefTable::load(const ResTable_lib_header* const header)
 {
     const uint32_t entryCount = dtohl(header->count);
@@ -7020,21 +7011,29 @@
     return NO_ERROR;
 }
 
+bool DynamicRefTable::requiresLookup(const Res_value* value) const {
+    // Only resolve non-dynamic references and attributes if the package is loaded as a
+    // library or if a shared library is attempting to retrieve its own resource
+    if ((value->dataType == Res_value::TYPE_REFERENCE ||
+         value->dataType == Res_value::TYPE_ATTRIBUTE) &&
+        (mAppAsLib || (Res_GETPACKAGE(value->data) + 1) == 0)) {
+        return true;
+    }
+    return value->dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE ||
+           value->dataType == Res_value::TYPE_DYNAMIC_REFERENCE;
+}
+
 status_t DynamicRefTable::lookupResourceValue(Res_value* value) const {
+    if (!requiresLookup(value)) {
+      return NO_ERROR;
+    }
+
     uint8_t resolvedType = Res_value::TYPE_REFERENCE;
     switch (value->dataType) {
         case Res_value::TYPE_ATTRIBUTE:
             resolvedType = Res_value::TYPE_ATTRIBUTE;
             FALLTHROUGH_INTENDED;
         case Res_value::TYPE_REFERENCE:
-            // Only resolve non-dynamic references and attributes if the package is loaded as a
-            // library or if a shared library is attempting to retrieve its own resource
-            if (!(mAppAsLib || (Res_GETPACKAGE(value->data) + 1) == 0)) {
-                return NO_ERROR;
-            }
-
-        // If the package is loaded as shared library, the resource reference
-        // also need to be fixed.
         break;
         case Res_value::TYPE_DYNAMIC_ATTRIBUTE:
             resolvedType = Res_value::TYPE_ATTRIBUTE;
diff --git a/libs/androidfw/TEST_MAPPING b/libs/androidfw/TEST_MAPPING
index a58b47f..d1a6a5c 100644
--- a/libs/androidfw/TEST_MAPPING
+++ b/libs/androidfw/TEST_MAPPING
@@ -3,6 +3,9 @@
     {
       "name": "libandroidfw_tests",
       "host": true
+    },
+    {
+      "name": "FrameworksResourceLoaderTests"
     }
   ]
 }
\ No newline at end of file
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index 625b6820..2047287 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -24,6 +24,7 @@
 #include "android-base/unique_fd.h"
 
 #include "androidfw/Asset.h"
+#include "androidfw/Idmap.h"
 #include "androidfw/LoadedArsc.h"
 #include "androidfw/misc.h"
 
@@ -95,10 +96,18 @@
     return loaded_arsc_.get();
   }
 
+  inline const LoadedIdmap* GetLoadedIdmap() const {
+    return loaded_idmap_.get();
+  }
+
   inline bool IsOverlay() const {
     return idmap_asset_.get() != nullptr;
   }
 
+  inline bool IsLoader() const {
+    return for_loader_;
+  }
+
   bool IsUpToDate() const;
 
   // Creates an Asset from any file on the file system.
@@ -127,10 +136,11 @@
   ZipArchivePtr zip_handle_;
   const std::string path_;
   time_t last_mod_time_;
-  bool for_loader;
+  bool for_loader_;
   std::unique_ptr<Asset> resources_asset_;
   std::unique_ptr<Asset> idmap_asset_;
   std::unique_ptr<const LoadedArsc> loaded_arsc_;
+  std::unique_ptr<const LoadedIdmap> loaded_idmap_;
 };
 
 }  // namespace android
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index c7348b1..20e4023 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -122,7 +122,7 @@
 
   // Returns the DynamicRefTable for the ApkAssets represented by the cookie.
   // This may be nullptr if the APK represented by `cookie` has no resource table.
-  const DynamicRefTable* GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const;
+  std::shared_ptr<const DynamicRefTable> GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const;
 
   // Returns a string representation of the overlayable API of a package.
   bool GetOverlayablesToString(const android::StringPiece& package_name,
@@ -236,12 +236,14 @@
                                    ResTable_config* in_out_selected_config, uint32_t* in_out_flags,
                                    uint32_t* out_last_reference) const;
 
-  // Enables or disables resource resolution logging. Clears stored steps when
-  // disabled.
+  // Resets the resource resolution structures in preparation for the next resource retrieval.
+  void ResetResourceResolution() const;
+
+  // Enables or disables resource resolution logging. Clears stored steps when disabled.
   void SetResourceResolutionLoggingEnabled(bool enabled);
 
-  // Returns formatted log of last resource resolution path, or empty if no
-  // resource has been resolved yet.
+  // Returns formatted log of last resource resolution path, or empty if no resource has been
+  // resolved yet.
   std::string GetLastResourceResolution() const;
 
   const std::vector<uint32_t> GetBagResIdStack(uint32_t resid);
@@ -264,7 +266,7 @@
   void ForEachPackage(const std::function<bool(const std::string&, uint8_t)> func) const {
     for (const PackageGroup& package_group : package_groups_) {
       if (!func(package_group.packages_.front().loaded_package_->GetPackageName(),
-           package_group.dynamic_ref_table.mAssignedPackageId)) {
+           package_group.dynamic_ref_table->mAssignedPackageId)) {
         return;
       }
     }
@@ -275,6 +277,50 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(AssetManager2);
 
+  // A collection of configurations and their associated ResTable_type that match the current
+  // AssetManager configuration.
+  struct FilteredConfigGroup {
+      std::vector<ResTable_config> configurations;
+      std::vector<const ResTable_type*> types;
+  };
+
+  // Represents an single package.
+  struct ConfiguredPackage {
+      // A pointer to the immutable, loaded package info.
+      const LoadedPackage* loaded_package_;
+
+      // A mutable AssetManager-specific list of configurations that match the AssetManager's
+      // current configuration. This is used as an optimization to avoid checking every single
+      // candidate configuration when looking up resources.
+      ByteBucketArray<FilteredConfigGroup> filtered_configs_;
+  };
+
+  // Represents a Runtime Resource Overlay that overlays resources in the logical package.
+  struct ConfiguredOverlay {
+      // The set of package groups that overlay this package group.
+      IdmapResMap overlay_res_maps_;
+
+      // The cookie of the overlay assets.
+      ApkAssetsCookie cookie;
+  };
+
+  // Represents a logical package, which can be made up of many individual packages. Each package
+  // in a PackageGroup shares the same package name and package ID.
+  struct PackageGroup {
+      // The set of packages that make-up this group.
+      std::vector<ConfiguredPackage> packages_;
+
+      // The cookies associated with each package in the group. They share the same order as
+      // packages_.
+      std::vector<ApkAssetsCookie> cookies_;
+
+      // Runtime Resource Overlays that overlay resources in this package group.
+      std::vector<ConfiguredOverlay> overlays_;
+
+      // A library reference table that contains build-package ID to runtime-package ID mappings.
+      std::shared_ptr<DynamicRefTable> dynamic_ref_table = std::make_shared<DynamicRefTable>();
+  };
+
   // Finds the best entry for `resid` from the set of ApkAssets. The entry can be a simple
   // Res_value, or a complex map/bag type. If successful, it is available in `out_entry`.
   // Returns kInvalidCookie on failure. Otherwise, the return value is the cookie associated with
@@ -295,6 +341,11 @@
   ApkAssetsCookie FindEntry(uint32_t resid, uint16_t density_override, bool stop_at_first_match,
                             bool ignore_configuration, FindEntryResult* out_entry) const;
 
+  ApkAssetsCookie FindEntryInternal(const PackageGroup& package_group, uint8_t type_idx,
+                                    uint16_t entry_idx, const ResTable_config& desired_config,
+                                    bool /*stop_at_first_match*/,
+                                    bool ignore_configuration, FindEntryResult* out_entry) const;
+
   // Assigns package IDs to all shared library ApkAssets.
   // Should be called whenever the ApkAssets are changed.
   void BuildDynamicRefTable();
@@ -307,6 +358,9 @@
   // This should always be called when mutating the AssetManager's configuration or ApkAssets set.
   void RebuildFilterList(bool filter_incompatible_configs = true);
 
+  // Retrieves the APK paths of overlays that overlay non-system packages.
+  std::set<std::string> GetNonSystemOverlayPaths() const;
+
   // AssetManager2::GetBag(resid) wraps this function to track which resource ids have already
   // been seen while traversing bag parents.
   const ResolvedBag* GetBag(uint32_t resid, std::vector<uint32_t>& child_resids);
@@ -318,38 +372,6 @@
   // have a longer lifetime.
   std::vector<const ApkAssets*> apk_assets_;
 
-  // A collection of configurations and their associated ResTable_type that match the current
-  // AssetManager configuration.
-  struct FilteredConfigGroup {
-    std::vector<ResTable_config> configurations;
-    std::vector<const ResTable_type*> types;
-  };
-
-  // Represents an single package.
-  struct ConfiguredPackage {
-    // A pointer to the immutable, loaded package info.
-    const LoadedPackage* loaded_package_;
-
-    // A mutable AssetManager-specific list of configurations that match the AssetManager's
-    // current configuration. This is used as an optimization to avoid checking every single
-    // candidate configuration when looking up resources.
-    ByteBucketArray<FilteredConfigGroup> filtered_configs_;
-  };
-
-  // Represents a logical package, which can be made up of many individual packages. Each package
-  // in a PackageGroup shares the same package name and package ID.
-  struct PackageGroup {
-    // The set of packages that make-up this group.
-    std::vector<ConfiguredPackage> packages_;
-
-    // The cookies associated with each package in the group. They share the same order as
-    // packages_.
-    std::vector<ApkAssetsCookie> cookies_;
-
-    // A library reference table that contains build-package ID to runtime-package ID mappings.
-    DynamicRefTable dynamic_ref_table;
-  };
-
   // DynamicRefTables for shared library package resolution.
   // These are ordered according to apk_assets_. The mappings may change depending on what is
   // in apk_assets_, therefore they must be stored in the AssetManager and not in the
@@ -418,7 +440,7 @@
   };
 
   // Record of the last resolved resource's resolution path.
-  mutable Resolution last_resolution;
+  mutable Resolution last_resolution_;
 };
 
 class Theme {
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index fd02e6f..ab4c9c2 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -20,20 +20,122 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <variant>
 
 #include "android-base/macros.h"
-
 #include "androidfw/StringPiece.h"
+#include "androidfw/ResourceTypes.h"
+#include "utils/ByteOrder.h"
 
 namespace android {
 
-struct Idmap_header;
-struct IdmapEntry_header;
+class LoadedIdmap;
+class IdmapResMap;
+
+// A string pool for overlay apk assets. The string pool holds the strings of the overlay resources
+// table and additionally allows for loading strings from the idmap string pool. The idmap string
+// pool strings are offset after the end of the overlay resource table string pool entries so
+// queries for strings defined inline in the idmap do not conflict with queries for overlay
+// resource table strings.
+class OverlayStringPool : public ResStringPool {
+ public:
+  virtual ~OverlayStringPool();
+  virtual const char16_t* stringAt(size_t idx, size_t* outLen) const;
+  virtual const char* string8At(size_t idx, size_t* outLen) const;
+
+  explicit OverlayStringPool(const LoadedIdmap* loaded_idmap);
+ private:
+    const Idmap_data_header* data_header_;
+    const ResStringPool* idmap_string_pool_;
+};
+
+// A dynamic reference table for loaded overlay packages that rewrites the resource id of overlay
+// resources to the resource id of corresponding target resources.
+class OverlayDynamicRefTable : public DynamicRefTable {
+ public:
+  virtual ~OverlayDynamicRefTable() = default;
+  virtual status_t lookupResourceId(uint32_t* resId) const;
+
+ private:
+  explicit OverlayDynamicRefTable(const Idmap_data_header* data_header,
+                                  const Idmap_overlay_entry* entries,
+                                  uint8_t target_assigned_package_id);
+
+  // Rewrites a compile-time overlay resource id to the runtime resource id of corresponding target
+  // resource.
+  virtual status_t lookupResourceIdNoRewrite(uint32_t* resId) const;
+
+  const Idmap_data_header* data_header_;
+  const Idmap_overlay_entry* entries_;
+  const int8_t target_assigned_package_id_;
+
+  friend LoadedIdmap;
+  friend IdmapResMap;
+};
+
+// A mapping of target resource ids to a values or resource ids that should overlay the target.
+class IdmapResMap {
+ public:
+  // Represents the result of a idmap lookup. The result can be one of three possibillities:
+  // 1) The result is a resource id which represents the overlay resource that should act as an
+  //    alias of the target resource.
+  // 2) The result is a table entry which overlays the type and value of the target resource.
+  // 3) The result is neither and the target resource is not overlaid.
+  class Result {
+   public:
+    Result() : data_(nullptr) {};
+    explicit Result(uint32_t value) : data_(value) {};
+    explicit Result(ResTable_entry_handle&& value) : data_(value) { };
+
+    // Returns `true` if the resource is overlaid.
+    inline explicit operator bool() const {
+      return !std::get_if<nullptr_t>(&data_);
+    }
+
+    inline bool IsResourceId() const {
+      return std::get_if<uint32_t>(&data_);
+    }
+
+    inline uint32_t GetResourceId() const {
+      return *std::get_if<uint32_t>(&data_);
+    }
+
+    inline bool IsTableEntry() const {
+      return std::get_if<ResTable_entry_handle>(&data_);
+    }
+
+    inline const ResTable_entry_handle& GetTableEntry() const {
+      return *std::get_if<ResTable_entry_handle>(&data_);
+    }
+
+   private:
+      std::variant<uint32_t, nullptr_t, ResTable_entry_handle> data_;
+  };
+
+  // Looks up the value that overlays the target resource id.
+  Result Lookup(uint32_t target_res_id) const;
+
+  inline const OverlayDynamicRefTable* GetOverlayDynamicRefTable() const {
+    return overlay_ref_table_;
+  }
+
+ private:
+  explicit IdmapResMap(const Idmap_data_header* data_header,
+                       const Idmap_target_entry* entries,
+                       uint8_t target_assigned_package_id,
+                       const OverlayDynamicRefTable* overlay_ref_table);
+
+  const Idmap_data_header* data_header_;
+  const Idmap_target_entry* entries_;
+  const uint8_t target_assigned_package_id_;
+  const OverlayDynamicRefTable* overlay_ref_table_;
+
+  friend LoadedIdmap;
+};
 
 // Represents a loaded/parsed IDMAP for a Runtime Resource Overlay (RRO).
-// An RRO and its target APK have different resource IDs assigned to their resources. Overlaying
-// a resource is done by resource name. An IDMAP is a generated mapping between the resource IDs
-// of the RRO and the target APK for each resource with the same name.
+// An RRO and its target APK have different resource IDs assigned to their resources.
+// An IDMAP is a generated mapping between the resource IDs of the RRO and the target APK.
 // A LoadedIdmap can be set alongside the overlay's LoadedArsc to allow the overlay ApkAssets to
 // masquerade as the target ApkAssets resources.
 class LoadedIdmap {
@@ -41,34 +143,52 @@
   // Loads an IDMAP from a chunk of memory. Returns nullptr if the IDMAP data was malformed.
   static std::unique_ptr<const LoadedIdmap> Load(const StringPiece& idmap_data);
 
-  // Performs a lookup of the expected entry ID for the given IDMAP entry header.
-  // Returns true if the mapping exists and fills `output_entry_id` with the result.
-  static bool Lookup(const IdmapEntry_header* header, uint16_t input_entry_id,
-                     uint16_t* output_entry_id);
-
-  // Returns the package ID for which this overlay should apply.
-  uint8_t TargetPackageId() const;
-
   // Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated.
   inline const std::string& OverlayApkPath() const {
     return overlay_apk_path_;
   }
 
-  // Returns the mapping of target entry ID to overlay entry ID for the given target type.
-  const IdmapEntry_header* GetEntryMapForType(uint8_t type_id) const;
+  // Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated.
+  inline const std::string& TargetApkPath() const {
+    return target_apk_path_;
+  }
+
+  // Returns a mapping from target resource ids to overlay values.
+  inline const IdmapResMap GetTargetResourcesMap(
+      uint8_t target_assigned_package_id, const OverlayDynamicRefTable* overlay_ref_table) const {
+    return IdmapResMap(data_header_, target_entries_, target_assigned_package_id,
+                       overlay_ref_table);
+  }
+
+  // Returns a dynamic reference table for a loaded overlay package.
+  inline const OverlayDynamicRefTable GetOverlayDynamicRefTable(
+      uint8_t target_assigned_package_id) const {
+    return OverlayDynamicRefTable(data_header_, overlay_entries_, target_assigned_package_id);
+  }
 
  protected:
   // Exposed as protected so that tests can subclass and mock this class out.
   LoadedIdmap() = default;
 
-  const Idmap_header* header_ = nullptr;
+  const Idmap_header* header_;
+  const Idmap_data_header* data_header_;
+  const Idmap_target_entry* target_entries_;
+  const Idmap_overlay_entry* overlay_entries_;
+  const std::unique_ptr<ResStringPool> string_pool_;
+
   std::string overlay_apk_path_;
-  std::unordered_map<uint8_t, const IdmapEntry_header*> type_map_;
+  std::string target_apk_path_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(LoadedIdmap);
 
-  explicit LoadedIdmap(const Idmap_header* header);
+  explicit LoadedIdmap(const Idmap_header* header,
+                       const Idmap_data_header* data_header,
+                       const Idmap_target_entry* target_entries,
+                       const Idmap_overlay_entry* overlay_entries,
+                       ResStringPool* string_pool);
+
+  friend OverlayStringPool;
 };
 
 }  // namespace android
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 1a56876..ba1beaa 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -51,10 +51,6 @@
   // and under which configurations it varies.
   const ResTable_typeSpec* type_spec;
 
-  // Pointer to the mmapped data where the IDMAP mappings for this type
-  // exist. May be nullptr if no IDMAP exists.
-  const IdmapEntry_header* idmap_entries;
-
   // The number of types that follow this struct.
   // There is a type for each configuration that entries are defined for.
   size_t type_count;
@@ -135,8 +131,7 @@
     return iterator(this, resource_ids_.size() + 1, 0);
   }
 
-  static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk,
-                                                   const LoadedIdmap* loaded_idmap, bool system,
+  static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk, bool system,
                                                    bool load_as_shared_library,
                                                    bool load_as_custom_loader);
 
@@ -183,11 +178,6 @@
     return system_;
   }
 
-  // Returns true if this package is from an overlay ApkAssets.
-  inline bool IsOverlay() const {
-    return overlay_;
-  }
-
   // Returns true if this package is a custom loader and should behave like an overlay
   inline bool IsCustomLoader() const {
     return custom_loader_;
@@ -222,9 +212,6 @@
       const TypeSpecPtr& ptr = type_specs_[i];
       if (ptr != nullptr) {
         uint8_t type_id = ptr->type_spec->id;
-        if (ptr->idmap_entries != nullptr) {
-          type_id = ptr->idmap_entries->target_type_id;
-        }
         f(ptr.get(), type_id - 1);
       }
     }
@@ -265,7 +252,6 @@
   int type_id_offset_ = 0;
   bool dynamic_ = false;
   bool system_ = false;
-  bool overlay_ = false;
   bool custom_loader_ = false;
   bool defines_overlayable_ = false;
 
@@ -298,7 +284,7 @@
   // Returns the string pool where all string resource values
   // (Res_value::dataType == Res_value::TYPE_STRING) are indexed.
   inline const ResStringPool* GetStringPool() const {
-    return &global_string_pool_;
+    return global_string_pool_.get();
   }
 
   // Gets a pointer to the package with the specified package ID, or nullptr if no such package
@@ -319,12 +305,8 @@
   DISALLOW_COPY_AND_ASSIGN(LoadedArsc);
 
   LoadedArsc() = default;
-  bool LoadTable(
-      const Chunk& chunk,
-      const LoadedIdmap* loaded_idmap,
-      bool load_as_shared_library,
-      bool for_loader
-  );
+  bool LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, bool load_as_shared_library,
+                 bool for_loader);
 
   static std::unique_ptr<const LoadedArsc> LoadData(std::unique_ptr<LoadedArsc>& loaded_arsc,
                                                     const char* data,
@@ -333,7 +315,7 @@
                                                     bool load_as_shared_library = false,
                                                     bool for_loader = false);
 
-  ResStringPool global_string_pool_;
+  std::unique_ptr<ResStringPool> global_string_pool_ = util::make_unique<ResStringPool>();
   std::vector<std::unique_ptr<const LoadedPackage>> packages_;
   bool system_ = false;
 };
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index c8ace90..b20e657 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -39,7 +39,7 @@
 namespace android {
 
 constexpr const static uint32_t kIdmapMagic = 0x504D4449u;
-constexpr const static uint32_t kIdmapCurrentVersion = 0x00000001u;
+constexpr const static uint32_t kIdmapCurrentVersion = 0x00000002u;
 
 /**
  * In C++11, char16_t is defined as *at least* 16 bits. We do a lot of
@@ -492,7 +492,7 @@
 public:
     ResStringPool();
     ResStringPool(const void* data, size_t size, bool copyData=false);
-    ~ResStringPool();
+    virtual ~ResStringPool();
 
     void setToEmpty();
     status_t setTo(const void* data, size_t size, bool copyData=false);
@@ -506,10 +506,10 @@
     inline const char16_t* stringAt(const ResStringPool_ref& ref, size_t* outLen) const {
         return stringAt(ref.index, outLen);
     }
-    const char16_t* stringAt(size_t idx, size_t* outLen) const;
+    virtual const char16_t* stringAt(size_t idx, size_t* outLen) const;
 
     // Note: returns null if the string pool is not UTF8.
-    const char* string8At(size_t idx, size_t* outLen) const;
+    virtual const char* string8At(size_t idx, size_t* outLen) const;
 
     // Return string whether the pool is UTF8 or UTF16.  Does not allow you
     // to distinguish null.
@@ -812,7 +812,7 @@
      * The tree stores a clone of the specified DynamicRefTable, so any changes to the original
      * DynamicRefTable will not affect this tree after instantiation.
      **/
-    explicit ResXMLTree(const DynamicRefTable* dynamicRefTable);
+    explicit ResXMLTree(std::shared_ptr<const DynamicRefTable> dynamicRefTable);
     ResXMLTree();
     ~ResXMLTree();
 
@@ -827,7 +827,7 @@
 
     status_t validateNode(const ResXMLTree_node* node) const;
 
-    std::unique_ptr<const DynamicRefTable> mDynamicRefTable;
+    std::shared_ptr<const DynamicRefTable> mDynamicRefTable;
 
     status_t                    mError;
     void*                       mOwnedData;
@@ -1584,6 +1584,50 @@
     Res_value value;
 };
 
+
+// A ResTable_entry variant that either holds an unmanaged pointer to a constant ResTable_entry or
+// holds a ResTable_entry which is tied to the lifetime of the handle.
+class ResTable_entry_handle {
+ public:
+    ResTable_entry_handle() = default;
+
+    ResTable_entry_handle(const ResTable_entry_handle& handle) {
+      entry_ = handle.entry_;
+    }
+
+    ResTable_entry_handle(ResTable_entry_handle&& handle) noexcept {
+      entry_ = handle.entry_;
+    }
+
+    inline static ResTable_entry_handle managed(ResTable_entry* entry)  {
+      return ResTable_entry_handle(std::shared_ptr<const ResTable_entry>(entry));
+    }
+
+    inline static ResTable_entry_handle unmanaged(const ResTable_entry* entry)  {
+      return ResTable_entry_handle(std::shared_ptr<const ResTable_entry>(entry, [](auto /*p */){}));
+    }
+
+    inline ResTable_entry_handle& operator=(const ResTable_entry_handle& handle) noexcept {
+      entry_ = handle.entry_;
+      return *this;
+    }
+
+    inline ResTable_entry_handle& operator=(ResTable_entry_handle&& handle) noexcept {
+      entry_ = handle.entry_;
+      return *this;
+    }
+
+    inline const ResTable_entry* operator*() & {
+      return entry_.get();
+    }
+
+ private:
+    explicit ResTable_entry_handle(std::shared_ptr<const ResTable_entry> entry)
+        : entry_(std::move(entry)) { }
+
+    std::shared_ptr<const ResTable_entry> entry_;
+};
+
 /**
  * A package-id to package name mapping for any shared libraries used
  * in this resource table. The package-id's encoded in this resource
@@ -1668,7 +1712,8 @@
   uint32_t entry_count;
 };
 
-struct alignas(uint32_t) Idmap_header {
+#pragma pack(push, 1)
+struct Idmap_header {
   // Always 0x504D4449 ('IDMP')
   uint32_t magic;
 
@@ -1679,18 +1724,28 @@
 
   uint8_t target_path[256];
   uint8_t overlay_path[256];
+};
 
-  uint16_t target_package_id;
-  uint16_t type_count;
-} __attribute__((packed));
+struct Idmap_data_header {
+  uint8_t target_package_id;
+  uint8_t overlay_package_id;
+  uint32_t target_entry_count;
+  uint32_t overlay_entry_count;
+  uint32_t string_pool_index_offset;
+  uint32_t string_pool_length;
+};
 
-struct alignas(uint32_t) IdmapEntry_header {
-  uint16_t target_type_id;
-  uint16_t overlay_type_id;
-  uint16_t entry_count;
-  uint16_t entry_id_offset;
-  uint32_t entries[0];
-} __attribute__((packed));
+struct Idmap_target_entry {
+  uint32_t target_id;
+  uint8_t type;
+  uint32_t value;
+};
+
+struct Idmap_overlay_entry {
+  uint32_t overlay_id;
+  uint32_t target_id;
+};
+#pragma pack(pop)
 
 class AssetManager2;
 
@@ -1708,6 +1763,7 @@
 public:
     DynamicRefTable();
     DynamicRefTable(uint8_t packageId, bool appAsLib);
+    virtual ~DynamicRefTable() = default;
 
     // Loads an unmapped reference table from the package.
     status_t load(const ResTable_lib_header* const header);
@@ -1721,12 +1777,12 @@
 
     void addMapping(uint8_t buildPackageId, uint8_t runtimePackageId);
 
-    // Creates a new clone of the reference table
-    std::unique_ptr<DynamicRefTable> clone() const;
+    // Returns whether or not the value must be looked up.
+    bool requiresLookup(const Res_value* value) const;
 
     // Performs the actual conversion of build-time resource ID to run-time
     // resource ID.
-    status_t lookupResourceId(uint32_t* resId) const;
+    virtual status_t lookupResourceId(uint32_t* resId) const;
     status_t lookupResourceValue(Res_value* value) const;
 
     inline const KeyedVector<String16, uint8_t>& entries() const {
diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp
index e2b9f00..0f2ee6f 100644
--- a/libs/androidfw/tests/ApkAssets_test.cpp
+++ b/libs/androidfw/tests/ApkAssets_test.cpp
@@ -79,39 +79,6 @@
   EXPECT_TRUE(loaded_arsc->GetPackages()[0]->IsDynamic());
 }
 
-TEST(ApkAssetsTest, LoadApkWithIdmap) {
-  std::string contents;
-  ResTable target_table;
-  const std::string target_path = GetTestDataPath() + "/basic/basic.apk";
-  ASSERT_TRUE(ReadFileFromZipToString(target_path, "resources.arsc", &contents));
-  ASSERT_THAT(target_table.add(contents.data(), contents.size(), 0, true /*copyData*/),
-              Eq(NO_ERROR));
-
-  ResTable overlay_table;
-  const std::string overlay_path = GetTestDataPath() + "/overlay/overlay.apk";
-  ASSERT_TRUE(ReadFileFromZipToString(overlay_path, "resources.arsc", &contents));
-  ASSERT_THAT(overlay_table.add(contents.data(), contents.size(), 0, true /*copyData*/),
-              Eq(NO_ERROR));
-
-  util::unique_cptr<void> idmap_data;
-  void* temp_data;
-  size_t idmap_len;
-
-  ASSERT_THAT(target_table.createIdmap(overlay_table, 0u, 0u, target_path.c_str(),
-                                       overlay_path.c_str(), &temp_data, &idmap_len),
-              Eq(NO_ERROR));
-  idmap_data.reset(temp_data);
-
-  TemporaryFile tf;
-  ASSERT_TRUE(base::WriteFully(tf.fd, idmap_data.get(), idmap_len));
-  close(tf.fd);
-
-  // Open something so that the destructor of TemporaryFile closes a valid fd.
-  tf.fd = open("/dev/null", O_WRONLY);
-
-  ASSERT_THAT(ApkAssets::LoadOverlay(tf.path), NotNull());
-}
-
 TEST(ApkAssetsTest, CreateAndDestroyAssetKeepsApkAssetsOpen) {
   std::unique_ptr<const ApkAssets> loaded_apk =
       ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 1591024..b3190be 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -718,15 +718,17 @@
 
   const auto map = assetmanager.GetOverlayableMapForPackage(0x7f);
   ASSERT_NE(nullptr, map);
-  ASSERT_EQ(2, map->size());
+  ASSERT_EQ(3, map->size());
   ASSERT_EQ(map->at("OverlayableResources1"), "overlay://theme");
   ASSERT_EQ(map->at("OverlayableResources2"), "overlay://com.android.overlayable");
+  ASSERT_EQ(map->at("OverlayableResources3"), "");
 
   std::string api;
   ASSERT_TRUE(assetmanager.GetOverlayablesToString("com.android.overlayable", &api));
   ASSERT_EQ(api.find("not_overlayable"), std::string::npos);
   ASSERT_NE(api.find("resource='com.android.overlayable:string/overlayable2' overlayable='OverlayableResources1' actor='overlay://theme' policy='0x0000000a'\n"),
             std::string::npos);
+
 }
 
 }  // namespace android
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index 10b83a7..b679672 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -14,114 +14,231 @@
  * limitations under the License.
  */
 
+#include "android-base/file.h"
+#include "androidfw/ApkAssets.h"
+#include "androidfw/AssetManager2.h"
 #include "androidfw/ResourceTypes.h"
 
 #include "utils/String16.h"
 #include "utils/String8.h"
 
 #include "TestHelpers.h"
-#include "data/basic/R.h"
+#include "data/overlay/R.h"
+#include "data/overlayable/R.h"
+#include "data/system/R.h"
 
-using ::com::android::basic::R;
+namespace overlay = com::android::overlay;
+namespace overlayable = com::android::overlayable;
 
 namespace android {
 
+namespace {
+
 class IdmapTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    std::string contents;
-    ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc",
-                                        &contents));
-    ASSERT_EQ(NO_ERROR, target_table_.add(contents.data(), contents.size(), 0, true));
+    // Move to the test data directory so the idmap can locate the overlay APK.
+    std::string original_path = base::GetExecutableDirectory();
+    chdir(GetTestDataPath().c_str());
 
-    ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlay/overlay.apk",
-                                        "resources.arsc", &overlay_data_));
-    ResTable overlay_table;
-    ASSERT_EQ(NO_ERROR, overlay_table.add(overlay_data_.data(), overlay_data_.size()));
+    system_assets_ = ApkAssets::Load("system/system.apk");
+    ASSERT_NE(nullptr, system_assets_);
 
-    char target_name[256] = "com.android.basic";
-    ASSERT_EQ(NO_ERROR, overlay_table.createIdmap(target_table_, 0, 0, target_name, target_name,
-                                                  &data_, &data_size_));
+    overlay_assets_ = ApkAssets::LoadOverlay("overlay/overlay.idmap");
+    ASSERT_NE(nullptr, overlay_assets_);
+
+    overlayable_assets_ = ApkAssets::Load("overlayable/overlayable.apk");
+    ASSERT_NE(nullptr, overlayable_assets_);
+    chdir(original_path.c_str());
   }
 
-  void TearDown() override {
-    ::free(data_);
-  }
-
-  ResTable target_table_;
-  std::string overlay_data_;
-  void* data_ = nullptr;
-  size_t data_size_ = 0;
+ protected:
+  std::unique_ptr<const ApkAssets> system_assets_;
+  std::unique_ptr<const ApkAssets> overlay_assets_;
+  std::unique_ptr<const ApkAssets> overlayable_assets_;
 };
 
-TEST_F(IdmapTest, CanLoadIdmap) {
-  ASSERT_EQ(NO_ERROR,
-            target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_));
+std::string GetStringFromApkAssets(const AssetManager2& asset_manager, const Res_value& value,
+                                   ApkAssetsCookie cookie) {
+  auto assets = asset_manager.GetApkAssets();
+  const ResStringPool* string_pool = assets[cookie]->GetLoadedArsc()->GetStringPool();
+  return GetStringFromPool(string_pool, value.data);
+}
+
 }
 
 TEST_F(IdmapTest, OverlayOverridesResourceValue) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
   Res_value val;
-  ssize_t block = target_table_.getResource(R::string::test2, &val, false);
-  ASSERT_GE(block, 0);
-  ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
-  const ResStringPool* pool = target_table_.getTableStringBlock(block);
-  ASSERT_TRUE(pool != NULL);
-  ASSERT_LT(val.data, pool->size());
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable5,
+                                                    false /* may_be_bag */,
+                                                    0 /* density_override */, &val, &config,
+                                                    &flags);
+  ASSERT_EQ(cookie, 2U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
+  ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "Overlay One");
+}
 
-  size_t str_len;
-  const char16_t* target_str16 = pool->stringAt(val.data, &str_len);
-  ASSERT_TRUE(target_str16 != NULL);
-  ASSERT_EQ(String16("test2"), String16(target_str16, str_len));
+TEST_F(IdmapTest, OverlayOverridesResourceValueUsingDifferentPackage) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
+  Res_value val;
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable10,
+                                                    false /* may_be_bag */,
+                                                    0 /* density_override */, &val, &config,
+                                                    &flags);
+  ASSERT_EQ(cookie, 0U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
+  ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "yes");
+}
 
-  ASSERT_EQ(NO_ERROR,
-            target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_));
+TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInternalResource) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
+  Res_value val;
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable8,
+                                                    false /* may_be_bag */,
+                                                    0 /* density_override */, &val, &config,
+                                                    &flags);
+  ASSERT_EQ(cookie, 2U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_REFERENCE);
+  ASSERT_EQ(val.data, (overlay::R::string::internal & 0x00ffffff) | (0x02 << 24));
+}
 
-  ssize_t new_block = target_table_.getResource(R::string::test2, &val, false);
-  ASSERT_GE(new_block, 0);
-  ASSERT_NE(block, new_block);
-  ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
-  pool = target_table_.getTableStringBlock(new_block);
-  ASSERT_TRUE(pool != NULL);
-  ASSERT_LT(val.data, pool->size());
+TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineInteger) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
+  Res_value val;
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::integer::config_integer,
+                                                  false /* may_be_bag */,
+                                                  0 /* density_override */, &val, &config,
+                                                  &flags);
+  ASSERT_EQ(cookie, 2U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_INT_DEC);
+  ASSERT_EQ(val.data, 42);
+}
 
-  target_str16 = pool->stringAt(val.data, &str_len);
-  ASSERT_TRUE(target_str16 != NULL);
-  ASSERT_EQ(String16("test2-overlay"), String16(target_str16, str_len));
+TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineString) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
+  Res_value val;
+  ResTable_config config;
+  uint32_t flags;
+
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable11,
+                                                  false /* may_be_bag */,
+                                                  0 /* density_override */, &val, &config,
+                                                  &flags);
+  ASSERT_EQ(cookie, 2U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
+  ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "Hardcoded string");
+}
+
+TEST_F(IdmapTest, OverlayOverridesResourceValueUsingOverlayingResource) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
+  Res_value val;
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable9,
+                                                    false /* may_be_bag */,
+                                                    0 /* density_override */, &val, &config,
+                                                    &flags);
+  ASSERT_EQ(cookie, 2U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_REFERENCE);
+  ASSERT_EQ(val.data, overlayable::R::string::overlayable7);
+}
+
+TEST_F(IdmapTest, OverlayOverridesXmlParser) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
+  Res_value val;
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::layout::hello_view,
+                                                    false /* may_be_bag */,
+                                                    0 /* density_override */, &val, &config,
+                                                    &flags);
+  ASSERT_EQ(cookie, 2U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
+  ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "res/layout/hello_view.xml");
+
+  auto asset = asset_manager.OpenNonAsset("res/layout/hello_view.xml", cookie,
+                                          Asset::ACCESS_RANDOM);
+  auto dynamic_ref_table = asset_manager.GetDynamicRefTableForCookie(cookie);
+  auto xml_tree = util::make_unique<ResXMLTree>(std::move(dynamic_ref_table));
+  status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), false);
+  ASSERT_EQ(err, NO_ERROR);
+
+  while (xml_tree->next() != ResXMLParser::START_TAG) { }
+
+  // The resource id of @id/hello_view should be rewritten to the resource id/hello_view within the
+  // target.
+  ASSERT_EQ(xml_tree->getAttributeNameResID(0), 0x010100d0 /* android:attr/id */);
+  ASSERT_EQ(xml_tree->getAttributeDataType(0), Res_value::TYPE_REFERENCE);
+  ASSERT_EQ(xml_tree->getAttributeData(0), overlayable::R::id::hello_view);
+
+  // The resource id of @android:string/yes should not be rewritten even though it overlays
+  // string/overlayable10 in the target.
+  ASSERT_EQ(xml_tree->getAttributeNameResID(1), 0x0101014f /* android:attr/text */);
+  ASSERT_EQ(xml_tree->getAttributeDataType(1), Res_value::TYPE_REFERENCE);
+  ASSERT_EQ(xml_tree->getAttributeData(1), 0x01040013 /* android:string/yes */);
+
+  // The resource id of the attribute within the overlay should be rewritten to the resource id of
+  // the attribute in the target.
+  ASSERT_EQ(xml_tree->getAttributeNameResID(2), overlayable::R::attr::max_lines);
+  ASSERT_EQ(xml_tree->getAttributeDataType(2), Res_value::TYPE_INT_DEC);
+  ASSERT_EQ(xml_tree->getAttributeData(2), 4);
 }
 
 TEST_F(IdmapTest, OverlaidResourceHasSameName) {
-  ASSERT_EQ(NO_ERROR,
-            target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_));
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
 
-  ResTable::resource_name res_name;
-  ASSERT_TRUE(target_table_.getResourceName(R::array::integerArray1, true, &res_name));
-
-  ASSERT_TRUE(res_name.package != NULL);
-  ASSERT_TRUE(res_name.type != NULL);
-  ASSERT_TRUE(res_name.name8 != NULL);
-
-  EXPECT_EQ(String16("com.android.basic"), String16(res_name.package, res_name.packageLen));
-  EXPECT_EQ(String16("array"), String16(res_name.type, res_name.typeLen));
-  EXPECT_EQ(String8("integerArray1"), String8(res_name.name8, res_name.nameLen));
+  AssetManager2::ResourceName name;
+  ASSERT_TRUE(asset_manager.GetResourceName(overlayable::R::string::overlayable9, &name));
+  ASSERT_EQ(std::string(name.package), "com.android.overlayable");
+  ASSERT_EQ(String16(name.type16), u"string");
+  ASSERT_EQ(std::string(name.entry), "overlayable9");
 }
 
-constexpr const uint32_t kNonOverlaidResourceId = 0x7fff0000u;
+TEST_F(IdmapTest, OverlayLoaderInterop) {
+  std::string contents;
+  auto loader_assets = ApkAssets::LoadArsc(GetTestDataPath() + "/loader/resources.arsc",
+                                           /* for_loader */ true);
 
-TEST_F(IdmapTest, OverlayDoesNotIncludeNonOverlaidResources) {
-  // First check that the resource we're trying to not include when overlaid is present when
-  // the overlay is loaded as a standalone APK.
-  ResTable table;
-  ASSERT_EQ(NO_ERROR, table.add(overlay_data_.data(), overlay_data_.size(), 0, true));
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({overlayable_assets_.get(), loader_assets.get(),
+                              overlay_assets_.get()});
 
   Res_value val;
-  ssize_t block = table.getResource(kNonOverlaidResourceId, &val, false /*mayBeBag*/);
-  ASSERT_GE(block, 0);
-
-  // Now add the overlay and verify that the unoverlaid resource is gone.
-  ASSERT_EQ(NO_ERROR,
-            target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_));
-  block = target_table_.getResource(kNonOverlaidResourceId, &val, false /*mayBeBag*/);
-  ASSERT_LT(block, 0);
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable11,
+                                                    false /* may_be_bag */,
+                                                    0 /* density_override */, &val, &config,
+                                                    &flags);
+  std::cout << asset_manager.GetLastResourceResolution();
+  ASSERT_EQ(cookie, 1U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
+  ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "loader");
 }
 
 }  // namespace
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index fd57a92..82dd335 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -144,7 +144,7 @@
                                       "resources.arsc", &contents));
 
   std::unique_ptr<const LoadedArsc> loaded_arsc =
-      LoadedArsc::Load(StringPiece(contents), nullptr /*loaded_idmap*/, false /*system*/,
+      LoadedArsc::Load(StringPiece(contents), nullptr /* loaded_idmap */, false /*system*/,
                        true /*load_as_shared_library*/);
   ASSERT_THAT(loaded_arsc, NotNull());
 
@@ -222,67 +222,13 @@
   ASSERT_THAT(type_spec->types[0], NotNull());
 }
 
-class MockLoadedIdmap : public LoadedIdmap {
- public:
-  MockLoadedIdmap() : LoadedIdmap() {
-    local_header_.magic = kIdmapMagic;
-    local_header_.version = kIdmapCurrentVersion;
-    local_header_.target_package_id = 0x08;
-    local_header_.type_count = 1;
-    header_ = &local_header_;
-
-    entry_header = util::unique_cptr<IdmapEntry_header>(
-        (IdmapEntry_header*)::malloc(sizeof(IdmapEntry_header) + sizeof(uint32_t)));
-    entry_header->target_type_id = 0x03;
-    entry_header->overlay_type_id = 0x02;
-    entry_header->entry_id_offset = 1;
-    entry_header->entry_count = 1;
-    entry_header->entries[0] = 0x00000000u;
-    type_map_[entry_header->overlay_type_id] = entry_header.get();
-  }
-
- private:
-  Idmap_header local_header_;
-  util::unique_cptr<IdmapEntry_header> entry_header;
-};
-
-TEST(LoadedArscTest, LoadOverlay) {
-  std::string contents;
-  ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlay/overlay.apk", "resources.arsc",
-                                      &contents));
-
-  MockLoadedIdmap loaded_idmap;
-
-  std::unique_ptr<const LoadedArsc> loaded_arsc =
-      LoadedArsc::Load(StringPiece(contents), &loaded_idmap);
-  ASSERT_THAT(loaded_arsc, NotNull());
-
-  const LoadedPackage* package = loaded_arsc->GetPackageById(0x08u);
-  ASSERT_THAT(package, NotNull());
-
-  const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(0x03u - 1);
-  ASSERT_THAT(type_spec, NotNull());
-  ASSERT_THAT(type_spec->type_count, Ge(1u));
-  ASSERT_THAT(type_spec->types[0], NotNull());
-
-  // The entry being overlaid doesn't exist at the original entry index.
-  ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0001u), IsNull());
-
-  // Since this is an overlay, the actual entry ID must be mapped.
-  ASSERT_THAT(type_spec->idmap_entries, NotNull());
-  uint16_t target_entry_id = 0u;
-  ASSERT_TRUE(LoadedIdmap::Lookup(type_spec->idmap_entries, 0x0001u, &target_entry_id));
-  ASSERT_THAT(target_entry_id, Eq(0x0u));
-  ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0000), NotNull());
-}
-
 TEST(LoadedArscTest, LoadOverlayable) {
   std::string contents;
   ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlayable/overlayable.apk",
                                       "resources.arsc", &contents));
 
   std::unique_ptr<const LoadedArsc> loaded_arsc =
-      LoadedArsc::Load(StringPiece(contents), nullptr /*loaded_idmap*/, false /*system*/,
+      LoadedArsc::Load(StringPiece(contents), nullptr /* loaded_idmap */, false /*system*/,
                        false /*load_as_shared_library*/);
 
   ASSERT_THAT(loaded_arsc, NotNull());
@@ -383,9 +329,10 @@
   ASSERT_EQ(std::string("com.android.overlayable"), packages[0]->GetPackageName());
 
   const auto map = packages[0]->GetOverlayableMap();
-  ASSERT_EQ(2, map.size());
+  ASSERT_EQ(3, map.size());
   ASSERT_EQ(map.at("OverlayableResources1"), "overlay://theme");
   ASSERT_EQ(map.at("OverlayableResources2"), "overlay://com.android.overlayable");
+  ASSERT_EQ(map.at("OverlayableResources3"), "");
 }
 
 TEST(LoadedArscTest, LoadCustomLoader) {
@@ -394,7 +341,6 @@
   std::unique_ptr<Asset>
       asset = ApkAssets::CreateAssetFromFile(GetTestDataPath() + "/loader/resources.arsc");
 
-  MockLoadedIdmap loaded_idmap;
   const StringPiece data(
       reinterpret_cast<const char*>(asset->getBuffer(true /*wordAligned*/)),
       asset->getLength());
@@ -404,13 +350,13 @@
   ASSERT_THAT(loaded_arsc, NotNull());
 
   const LoadedPackage* package =
-      loaded_arsc->GetPackageById(get_package_id(android::R::string::cancel));
+      loaded_arsc->GetPackageById(get_package_id(overlayable::R::string::overlayable11));
   ASSERT_THAT(package, NotNull());
-  EXPECT_THAT(package->GetPackageName(), StrEq("android"));
-  EXPECT_THAT(package->GetPackageId(), Eq(0x01));
+  EXPECT_THAT(package->GetPackageName(), StrEq("com.android.loader"));
+  EXPECT_THAT(package->GetPackageId(), Eq(0x7f));
 
-  const uint8_t type_index = get_type_id(android::R::string::cancel) - 1;
-  const uint16_t entry_index = get_entry_id(android::R::string::cancel);
+  const uint8_t type_index = get_type_id(overlayable::R::string::overlayable11) - 1;
+  const uint16_t entry_index = get_entry_id(overlayable::R::string::overlayable11);
 
   const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
   ASSERT_THAT(type_spec, NotNull());
diff --git a/libs/androidfw/tests/data/loader/AndroidManifest.xml b/libs/androidfw/tests/data/loader/AndroidManifest.xml
new file mode 100644
index 0000000..4c0bb47
--- /dev/null
+++ b/libs/androidfw/tests/data/loader/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest package="com.android.loader">
+    <application>
+    </application>
+</manifest>
diff --git a/libs/androidfw/tests/data/loader/build b/libs/androidfw/tests/data/loader/build
new file mode 100755
index 0000000..457ec51
--- /dev/null
+++ b/libs/androidfw/tests/data/loader/build
@@ -0,0 +1,27 @@
+#!/bin/bash
+#
+# 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.
+#
+
+set -e
+
+FRAMEWORK_RES_APK=${ANDROID_PRODUCT_OUT}/system/framework/framework-res.apk
+
+rm resources.arsc
+aapt2 compile --dir res -o compiled.flata
+aapt2 link -I $FRAMEWORK_RES_APK --manifest AndroidManifest.xml -o loader.apk compiled.flata
+unzip loader.apk resources.arsc
+rm loader.apk
+rm compiled.flata
diff --git a/libs/androidfw/tests/data/loader/res/values/public.xml b/libs/androidfw/tests/data/loader/res/values/public.xml
new file mode 100644
index 0000000..3293229
--- /dev/null
+++ b/libs/androidfw/tests/data/loader/res/values/public.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <public type="string" name="overlayable11" id="0x7f01000b" />
+</resources>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/loader/res/values/values.xml b/libs/androidfw/tests/data/loader/res/values/values.xml
new file mode 100644
index 0000000..0653536
--- /dev/null
+++ b/libs/androidfw/tests/data/loader/res/values/values.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <string name="overlayable11">loader</string>
+</resources>
diff --git a/libs/androidfw/tests/data/loader/resources.arsc b/libs/androidfw/tests/data/loader/resources.arsc
index 2c881f2..2bdb288 100644
--- a/libs/androidfw/tests/data/loader/resources.arsc
+++ b/libs/androidfw/tests/data/loader/resources.arsc
Binary files differ
diff --git a/libs/androidfw/tests/data/overlay/AndroidManifest.xml b/libs/androidfw/tests/data/overlay/AndroidManifest.xml
index a56ac18..28a1148 100644
--- a/libs/androidfw/tests/data/overlay/AndroidManifest.xml
+++ b/libs/androidfw/tests/data/overlay/AndroidManifest.xml
@@ -15,7 +15,9 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.test.basic">
-    <application>
-    </application>
+    package="com.android.test.overlay">
+    <overlay
+        android:targetPackage="com.android.test.basic"
+        android:targetName="OverlayableResources3"
+        android:resourcesMap="@xml/overlays"/>
 </manifest>
diff --git a/libs/androidfw/tests/data/overlay/R.h b/libs/androidfw/tests/data/overlay/R.h
new file mode 100644
index 0000000..f3dbed2
--- /dev/null
+++ b/libs/androidfw/tests/data/overlay/R.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef TESTS_DATA_OVERLAY_R_H_
+#define TESTS_DATA_OVERLAY_R_H_
+
+#include <cstdint>
+
+namespace com {
+namespace android {
+namespace overlay {
+
+struct R {
+  struct string {
+    enum : uint32_t {
+      internal = 0x7f040000,
+    };
+  };
+};
+
+}  // namespace overlay
+}  // namespace android
+}  // namespace com
+
+#endif /* TESTS_DATA_OVERLAY_R_H_ */
diff --git a/libs/androidfw/tests/data/overlay/build b/libs/androidfw/tests/data/overlay/build
index 716b1bd..99dfd63 100755
--- a/libs/androidfw/tests/data/overlay/build
+++ b/libs/androidfw/tests/data/overlay/build
@@ -17,6 +17,15 @@
 
 set -e
 
+FRAMEWORK_RES_APK=${ANDROID_PRODUCT_OUT}/system/framework/framework-res.apk
+
 aapt2 compile --dir res -o compiled.flata
-aapt2 link --manifest AndroidManifest.xml -o overlay.apk compiled.flata
+aapt2 link -I $FRAMEWORK_RES_APK --manifest AndroidManifest.xml -o overlay.apk compiled.flata \
+    --no-auto-version
 rm compiled.flata
+
+# Navigate back a directory so the idmap can find the overlays in the test data directory when being
+# loaded during testing.
+cd ../
+idmap2 create --target-apk-path overlayable/overlayable.apk \
+    --overlay-apk-path overlay/overlay.apk --idmap-path overlay/overlay.idmap
diff --git a/libs/androidfw/tests/data/overlay/overlay.apk b/libs/androidfw/tests/data/overlay/overlay.apk
index d37874d..c594b8e 100644
--- a/libs/androidfw/tests/data/overlay/overlay.apk
+++ b/libs/androidfw/tests/data/overlay/overlay.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/overlay/overlay.idmap b/libs/androidfw/tests/data/overlay/overlay.idmap
new file mode 100644
index 0000000..27cf792f
--- /dev/null
+++ b/libs/androidfw/tests/data/overlay/overlay.idmap
Binary files differ
diff --git a/libs/androidfw/tests/data/overlay/res/layout/hello_view.xml b/libs/androidfw/tests/data/overlay/res/layout/hello_view.xml
new file mode 100644
index 0000000..54dc6c0
--- /dev/null
+++ b/libs/androidfw/tests/data/overlay/res/layout/hello_view.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/hello_view"
+    android:text="@android:string/yes"
+    app:max_lines="4"/>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/overlay/res/values/values.xml b/libs/androidfw/tests/data/overlay/res/values/values.xml
index 8e4417e..ba018ec 100644
--- a/libs/androidfw/tests/data/overlay/res/values/values.xml
+++ b/libs/androidfw/tests/data/overlay/res/values/values.xml
@@ -13,13 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <resources>
-    <string name="test2">test2-overlay</string>
-    <integer-array name="integerArray1">
-        <item>10</item>
-        <item>11</item>
-    </integer-array>
-    <public type="animator" name="unoverlaid" id="0x7fff0000" />
-    <item type="animator" name="unoverlaid">@null</item>
+    <string name="overlay1">Overlay One</string>
+    <string name="overlay2">Overlay Two</string>
+    <string name="overlay3">@string/internal</string>
+    <string name="overlay4">@string/overlay2</string>
+    <string name="internal">Internal</string>
+    <attr name="max_lines" format="integer" />
 </resources>
diff --git a/libs/androidfw/tests/data/overlay/res/xml/overlays.xml b/libs/androidfw/tests/data/overlay/res/xml/overlays.xml
new file mode 100644
index 0000000..9eca2fa
--- /dev/null
+++ b/libs/androidfw/tests/data/overlay/res/xml/overlays.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language language governing permissions and
+     limitations under the License.
+-->
+<overlay>
+    <!-- Overlays string/overlayable5 with the string "Overlay One". -->
+    <item target="string/overlayable5" value="@string/overlay1"/>
+
+    <!-- Overlays string/overlayable6 and string/overlayable7 with the string "Overlay Two". -->
+    <item target="string/overlayable7" value="@string/overlay2" />
+    <item target="string/overlayable6" value="@string/overlay2" />
+
+    <!-- Overlays string/overlayable8 with a reference to @string/internal. -->
+    <item target="string/overlayable8" value="@string/overlay3" />
+
+    <!-- Overlays string/overlayable9 with a reference to @string/overlay2. The reference to
+         @string/overlay2 should be rewritten to @string/overlayable7 in the target. -->
+    <item target="string/overlayable9" value="@string/overlay4" />
+
+    <!-- Overlays string/overlayable10 with the string "yes". -->
+    <item target="string/overlayable10" value="@android:string/yes" />
+
+    <!-- Overlays string/overlayable11 with the string "Hardcoded string". -->
+    <item target="string/overlayable11" value="Hardcoded string" />
+
+    <!-- Overlays string/overlayable10 with the string "yes". -->
+    <item target="integer/config_int" value="42" />
+
+    <!-- @attr/max_lines and @id/hello_view should be rewritten to @attr/max_lines and
+         @id/hello_view in the target. -->
+    <item target="layout/hello_view" value="@layout/hello_view" />
+    <item target="attr/max_lines" value="@attr/max_lines" />
+    <item target="id/hello_view" value="@id/hello_view" />
+</overlay>
+
+
diff --git a/libs/androidfw/tests/data/overlayable/R.h b/libs/androidfw/tests/data/overlayable/R.h
index e46e264d..35125a6 100644
--- a/libs/androidfw/tests/data/overlayable/R.h
+++ b/libs/androidfw/tests/data/overlayable/R.h
@@ -31,6 +31,43 @@
       overlayable2 = 0x7f010002,
       overlayable3 = 0x7f010003,
       overlayable4 = 0x7f010004,
+      overlayable5 = 0x7f010005,
+      overlayable6 = 0x7f010006,
+      overlayable7 = 0x7f010007,
+      overlayable8 = 0x7f010008,
+      overlayable9 = 0x7f010009,
+      overlayable10 = 0x7f01000a,
+      overlayable11 = 0x7f01000b,
+    };
+  };
+
+  struct attr {
+    enum : uint32_t  {
+      max_lines = 0x7f020000,
+    };
+  };
+
+  struct boolean {
+    enum : uint32_t {
+      config_bool = 0x7f030000,
+    };
+  };
+
+  struct id {
+    enum : uint32_t  {
+      hello_view = 0x7f040000,
+    };
+  };
+
+  struct integer {
+    enum : uint32_t {
+      config_integer = 0x7f050000,
+    };
+  };
+
+  struct layout {
+    enum : uint32_t  {
+      hello_view = 0x7f060000,
     };
   };
 };
diff --git a/libs/androidfw/tests/data/overlayable/build b/libs/androidfw/tests/data/overlayable/build
index 98fdc51..0aa97d6 100755
--- a/libs/androidfw/tests/data/overlayable/build
+++ b/libs/androidfw/tests/data/overlayable/build
@@ -17,6 +17,9 @@
 
 set -e
 
+FRAMEWORK_RES_APK=${ANDROID_PRODUCT_OUT}/system/framework/framework-res.apk
+
 aapt2 compile --dir res -o compiled.flata
-aapt2 link --manifest AndroidManifest.xml -o overlayable.apk compiled.flata
+aapt2 link -I $FRAMEWORK_RES_APK --manifest AndroidManifest.xml -o overlayable.apk compiled.flata \
+    --no-auto-version
 rm compiled.flata
diff --git a/libs/androidfw/tests/data/overlayable/overlayable.apk b/libs/androidfw/tests/data/overlayable/overlayable.apk
index 047e6af..9dc9c15 100644
--- a/libs/androidfw/tests/data/overlayable/overlayable.apk
+++ b/libs/androidfw/tests/data/overlayable/overlayable.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/overlayable/res/layout/hello_view.xml b/libs/androidfw/tests/data/overlayable/res/layout/hello_view.xml
new file mode 100644
index 0000000..268118a
--- /dev/null
+++ b/libs/androidfw/tests/data/overlayable/res/layout/hello_view.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/hello_view"
+    android:text="None"
+    app:max_lines="0"/>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
index fcdbe94..b3e8f7d 100644
--- a/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
+++ b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
@@ -15,27 +15,41 @@
 -->
 
 <resources>
-<overlayable name="OverlayableResources1" actor="overlay://theme">
-    <!-- Any overlay can overlay the value of @string/overlayable1 -->
-    <item type="string" name="overlayable1" />
+    <overlayable name="OverlayableResources1" actor="overlay://theme">
+        <!-- Any overlay on the product or system partition can overlay the value of
+            @string/overlayable2 -->
+        <policy type="product|system">
+            <item type="string" name="overlayable2" />
+        </policy>
 
-    <!-- Any overlay on the product or system partition can overlay the value of
-        @string/overlayable2 -->
-    <policy type="product|system">
-        <item type="string" name="overlayable2" />
-    </policy>
+        <!-- Any overlay can overlay the value of @string/overlayable4 -->
+        <policy type="public">
+            <item type="string" name="overlayable1" />
+            <item type="string" name="overlayable4" />
+        </policy>
+    </overlayable>
 
-    <!-- Any overlay can overlay the value of @string/overlayable4 -->
-    <policy type="public">
-        <item type="string" name="overlayable4" />
-    </policy>
-</overlayable>
+    <overlayable name="OverlayableResources2" actor="overlay://com.android.overlayable">
+        <!-- Any overlay on the vendor or product partition can overlay the value of
+            @string/overlayable3 -->
+        <policy type="vendor|product">
+            <item type="string" name="overlayable3" />
+        </policy>
+    </overlayable>
 
-<overlayable name="OverlayableResources2" actor="overlay://com.android.overlayable">
-    <!-- Any overlay on the vendor or product partition can overlay the value of
-        @string/overlayable3 -->
-    <policy type="vendor|product">
-        <item type="string" name="overlayable3" />
-    </policy>
-</overlayable>
+    <overlayable name="OverlayableResources3">
+        <policy type="public">
+            <item type="string" name="overlayable5" />
+            <item type="string" name="overlayable6" />
+            <item type="string" name="overlayable7" />
+            <item type="string" name="overlayable8" />
+            <item type="string" name="overlayable9" />
+            <item type="string" name="overlayable10" />
+            <item type="string" name="overlayable11" />
+            <item type="integer" name="config_int" />
+            <item type="id" name="hello_view" />
+            <item type="attr" name="max_lines" />
+            <item type="layout" name="hello_view" />
+        </policy>
+    </overlayable>
 </resources>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/overlayable/res/values/public.xml b/libs/androidfw/tests/data/overlayable/res/values/public.xml
index 5676d7c..042a311 100644
--- a/libs/androidfw/tests/data/overlayable/res/values/public.xml
+++ b/libs/androidfw/tests/data/overlayable/res/values/public.xml
@@ -20,4 +20,21 @@
     <public type="string" name="overlayable2" id="0x7f010002" />
     <public type="string" name="overlayable3" id="0x7f010003" />
     <public type="string" name="overlayable4" id="0x7f010004" />
+    <public type="string" name="overlayable5" id="0x7f010005" />
+    <public type="string" name="overlayable6" id="0x7f010006" />
+    <public type="string" name="overlayable7" id="0x7f010007" />
+    <public type="string" name="overlayable8" id="0x7f010008" />
+    <public type="string" name="overlayable9" id="0x7f010009" />
+    <public type="string" name="overlayable10" id="0x7f01000a" />
+    <public type="string" name="overlayable11" id="0x7f01000b" />
+
+    <public type="attr" name="max_lines" id="0x7f020000" />
+
+    <public type="bool" name="config_bool" id="0x7f030000" />
+
+    <public type="id" name="hello_view" id="0x7f040000" />
+
+    <public type="integer" name="config_int" id="0x7f050000" />
+
+    <public type="layout" name="hello_view" id="0x7f060000" />
 </resources>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/overlayable/res/values/values.xml b/libs/androidfw/tests/data/overlayable/res/values/values.xml
index a86b312..235772d 100644
--- a/libs/androidfw/tests/data/overlayable/res/values/values.xml
+++ b/libs/androidfw/tests/data/overlayable/res/values/values.xml
@@ -20,4 +20,15 @@
     <string name="overlayable2">Overlayable Two</string>
     <string name="overlayable3">Overlayable Three</string>
     <string name="overlayable4">Overlayable Four</string>
+    <string name="overlayable5">Overlayable Five</string>
+    <string name="overlayable6">Overlayable Six</string>
+    <string name="overlayable7">Overlayable Seven</string>
+    <string name="overlayable8">Overlayable Eight</string>
+    <string name="overlayable9">Overlayable Nine</string>
+    <string name="overlayable10">Overlayable Ten</string>
+    <string name="overlayable11">Overlayable Eleven</string>
+
+    <integer name="config_int">0</integer>
+    <bool name="config_bool">false</bool>
+    <attr name="max_lines" format="integer" />
 </resources>
diff --git a/libs/androidfw/tests/data/system/R.h b/libs/androidfw/tests/data/system/R.h
index 3741074..c0160c0 100644
--- a/libs/androidfw/tests/data/system/R.h
+++ b/libs/androidfw/tests/data/system/R.h
@@ -43,7 +43,8 @@
 
   struct string {
     enum : uint32_t {
-      cancel = 0x01040000,
+      no = 0x01040009,
+      yes = 0x01040013,
     };
   };
 };
diff --git a/libs/androidfw/tests/data/system/res/values/public.xml b/libs/androidfw/tests/data/system/res/values/public.xml
new file mode 100644
index 0000000..077874d
--- /dev/null
+++ b/libs/androidfw/tests/data/system/res/values/public.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <public type="string" name="no" id="0x01040009" />
+    <public type="string" name="yes" id="0x01040013" />
+</resources>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/system/res/values/values.xml b/libs/androidfw/tests/data/system/res/values/values.xml
new file mode 100644
index 0000000..0629c1d1
--- /dev/null
+++ b/libs/androidfw/tests/data/system/res/values/values.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<resources>
+    <string name="yes">yes</string>
+    <string name="no">no</string>
+</resources>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/system/system.apk b/libs/androidfw/tests/data/system/system.apk
index 9045d6c..1f7e007 100644
--- a/libs/androidfw/tests/data/system/system.apk
+++ b/libs/androidfw/tests/data/system/system.apk
Binary files differ
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index ae90f11..61b72cf 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -26,8 +26,10 @@
         // a problem
         "-Wno-free-nonheap-object",
 
-        // clang's warning is broken, see: https://llvm.org/bugs/show_bug.cgi?id=21629
-        "-Wno-missing-braces",
+        // Clang is producing non-determistic binary when the new pass manager is
+        // enabled. Disable the new PM as a temporary workaround.
+        // b/142372146
+        "-fno-experimental-new-pass-manager",
     ],
 
     include_dirs: [
diff --git a/libs/hwui/DamageAccumulator.h b/libs/hwui/DamageAccumulator.h
index 7d0b687..030a20f 100644
--- a/libs/hwui/DamageAccumulator.h
+++ b/libs/hwui/DamageAccumulator.h
@@ -27,7 +27,7 @@
 // Smaller than INT_MIN/INT_MAX because we offset these values
 // and thus don't want to be adding offsets to INT_MAX, that's bad
 #define DIRTY_MIN (-0x7ffffff - 1)
-#define DIRTY_MAX (0x7ffffff)
+#define DIRTY_MAX (0x8000000)
 
 namespace android {
 namespace uirenderer {
diff --git a/location/java/android/location/AbstractListenerManager.java b/location/java/android/location/AbstractListenerManager.java
index c41023e..944ebf9 100644
--- a/location/java/android/location/AbstractListenerManager.java
+++ b/location/java/android/location/AbstractListenerManager.java
@@ -42,8 +42,8 @@
         @Nullable private volatile T mListener;
 
         private Registration(Executor executor, T listener) {
-            Preconditions.checkArgument(listener != null);
-            Preconditions.checkArgument(executor != null);
+            Preconditions.checkArgument(listener != null, "invalid null listener/callback");
+            Preconditions.checkArgument(executor != null, "invalid null executor");
             mExecutor = executor;
             mListener = listener;
         }
@@ -83,16 +83,18 @@
         return addInternal(listener, executor);
     }
 
-    protected final boolean addInternal(Object listener, Handler handler) throws RemoteException {
+    protected final boolean addInternal(@NonNull Object listener, @NonNull Handler handler)
+            throws RemoteException {
         return addInternal(listener, new HandlerExecutor(handler));
     }
 
-    protected final boolean addInternal(Object listener, Executor executor) throws RemoteException {
+    protected final boolean addInternal(@NonNull Object listener, @NonNull Executor executor)
+            throws RemoteException {
+        Preconditions.checkArgument(listener != null, "invalid null listener/callback");
         return addInternal(listener, new Registration<>(executor, convertKey(listener)));
     }
 
     private boolean addInternal(Object key, Registration<T> registration) throws RemoteException {
-        Preconditions.checkNotNull(key);
         Preconditions.checkNotNull(registration);
 
         synchronized (mListeners) {
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index d06ba12..91f3a20 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -31,6 +31,7 @@
 import android.location.LocationRequest;
 import android.location.LocationTime;
 import android.os.Bundle;
+import android.os.ICancellationSignal;
 
 import com.android.internal.location.ProviderProperties;
 
@@ -41,16 +42,19 @@
  */
 interface ILocationManager
 {
+    Location getLastLocation(in LocationRequest request, String packageName);
+    boolean getCurrentLocation(in LocationRequest request,
+            in ICancellationSignal cancellationSignal, in ILocationListener listener,
+            String packageName, String listenerIdentifier);
+
     void requestLocationUpdates(in LocationRequest request, in ILocationListener listener,
-            in PendingIntent intent, String packageName);
+            in PendingIntent intent, String packageName, String listenerIdentifier);
     void removeUpdates(in ILocationListener listener, in PendingIntent intent, String packageName);
 
     void requestGeofence(in LocationRequest request, in Geofence geofence,
-            in PendingIntent intent, String packageName);
+            in PendingIntent intent, String packageName, String listenerIdentifier);
     void removeGeofence(in Geofence fence, in PendingIntent intent, String packageName);
 
-    Location getLastLocation(in LocationRequest request, String packageName);
-
     boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName);
     void unregisterGnssStatusCallback(IGnssStatusListener callback);
 
@@ -64,22 +68,23 @@
 
     boolean sendNiResponse(int notifId, int userResponse);
 
-    boolean addGnssMeasurementsListener(in IGnssMeasurementsListener listener, in String packageName);
+    boolean addGnssMeasurementsListener(in IGnssMeasurementsListener listener,
+             String packageName, String listenerIdentifier);
     void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections,
             in String packageName);
     long getGnssCapabilities(in String packageName);
     void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener);
 
-    boolean addGnssNavigationMessageListener(
-            in IGnssNavigationMessageListener listener,
-            in String packageName);
+    boolean addGnssNavigationMessageListener(in IGnssNavigationMessageListener listener,
+             String packageName, String listenerIdentifier);
     void removeGnssNavigationMessageListener(in IGnssNavigationMessageListener listener);
 
     int getGnssYearOfHardware();
     String getGnssHardwareModelName();
 
     int getGnssBatchSize(String packageName);
-    boolean addGnssBatchingCallback(in IBatchedLocationCallback callback, String packageName);
+    boolean addGnssBatchingCallback(in IBatchedLocationCallback callback, String packageName,
+             String listenerIdentifier);
     void removeGnssBatchingCallback();
     boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName);
     void flushGnssBatch(String packageName);
@@ -92,6 +97,7 @@
     String getBestProvider(in Criteria criteria, boolean enabledOnly);
     ProviderProperties getProviderProperties(String provider);
     boolean isProviderPackage(String packageName);
+    List<String> getProviderPackages(String provider);
 
     void setExtraLocationControllerPackage(String packageName);
     String getExtraLocationControllerPackage();
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 6824be8..27274d1 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -1211,7 +1211,8 @@
     }
 
     /**
-     * Attaches an extra {@link Location} to this Location.
+     * Attaches an extra {@link Location} to this Location. This is useful for location providers
+     * to set the {@link #EXTRA_NO_GPS_LOCATION} extra to provide coarse locations for clients.
      *
      * @param key the key associated with the Location extra
      * @param value the Location to attach
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 90e29df..9e17e95 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -20,6 +20,7 @@
 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
 import static android.Manifest.permission.LOCATION_HARDWARE;
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
+import static android.app.AlarmManager.ELAPSED_REALTIME;
 
 import android.Manifest;
 import android.annotation.CallbackExecutor;
@@ -31,17 +32,21 @@
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
+import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.HandlerExecutor;
+import android.os.ICancellationSignal;
 import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.ArrayMap;
@@ -51,9 +56,11 @@
 import com.android.internal.location.ProviderProperties;
 import com.android.internal.util.Preconditions;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Executor;
 import java.util.concurrent.RejectedExecutionException;
+import java.util.function.Consumer;
 
 /**
  * This class provides access to the system location services. These services allow applications to
@@ -76,22 +83,20 @@
 
     /**
      * Name of the network location provider.
-     * <p>This provider determines location based on
-     * availability of cell tower and WiFi access points. Results are retrieved
-     * by means of a network lookup.
+     *
+     * <p>This provider determines location based on nearby of cell tower and WiFi access points.
+     * Results are retrieved by means of a network lookup.
      */
     public static final String NETWORK_PROVIDER = "network";
 
     /**
-     * Name of the GPS location provider.
+     * Name of the GNSS location provider.
      *
-     * <p>This provider determines location using
-     * satellites. Depending on conditions, this provider may take a while to return
-     * a location fix. Requires the permission
-     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+     * <p>This provider determines location using GNSS satellites. Depending on conditions, this
+     * provider may take a while to return a location fix. Requires the
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
      *
-     * <p> The extras Bundle for the GPS location provider can contain the
-     * following key/value pairs:
+     * <p>The extras Bundle for the GPS location provider can contain the following key/value pairs:
      * <ul>
      * <li> satellites - the number of satellites used to derive the fix
      * </ul>
@@ -99,26 +104,24 @@
     public static final String GPS_PROVIDER = "gps";
 
     /**
-     * A special location provider for receiving locations without actually initiating
-     * a location fix.
+     * A special location provider for receiving locations without actually initiating a location
+     * fix.
      *
-     * <p>This provider can be used to passively receive location updates
-     * when other applications or services request them without actually requesting
-     * the locations yourself.  This provider will return locations generated by other
-     * providers.  You can query the {@link Location#getProvider()} method to determine
-     * the origin of the location update. Requires the permission
-     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}, although if the GPS is
-     * not enabled this provider might only return coarse fixes.
+     * <p>This provider can be used to passively receive location updates when other applications or
+     * services request them without actually requesting the locations yourself. This provider will
+     * only return locations generated by other providers.  You can query the
+     * {@link Location#getProvider()} method to determine the actual provider that supplied the
+     * location update. Requires the {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
+     * permission, although there is no guarantee of fine locations.
      */
     public static final String PASSIVE_PROVIDER = "passive";
 
     /**
-     * Name of the Fused location provider.
+     * The fused location provider.
      *
-     * <p>This provider combines inputs for all possible location sources
-     * to provide the best possible Location fix. It is implicitly
-     * used for all API's that involve the {@link LocationRequest}
-     * object.
+     * <p>This provider combines may combine inputs from several location sources to provide the
+     * best possible location fix. It is implicitly used for all API's that involve the
+     * {@link LocationRequest} object.
      *
      * @hide
      */
@@ -227,6 +230,8 @@
     public static final String METADATA_SETTINGS_FOOTER_STRING =
             "com.android.settings.location.FOOTER_STRING";
 
+    private static final long GET_CURRENT_LOCATION_TIMEOUT_MS = 30 * 1000;
+
     private final Context mContext;
 
     @UnsupportedAppUsage
@@ -521,6 +526,13 @@
      * location. The returned location may be quite old in some circumstances, so the age of the
      * location should always be checked.
      *
+     * <p>This will never activate sensors to compute a new location, and will only ever return a
+     * cached location.
+     *
+     * <p>See also {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)} which
+     * will always attempt to return a current location, but will potentially use additional power
+     * in the course of the attempt as compared to this method.
+     *
      * @param provider the name of the provider
      * @return the last known location for the given provider, or null if not available
      * @throws SecurityException if no suitable permission is present
@@ -542,26 +554,124 @@
     }
 
     /**
-     * Register for a single location update using the named provider and
-     * a callback.
+     * Create a string that allows an app to identify a listener
      *
-     * <p>See {@link #requestLocationUpdates(String, long, float, LocationListener, Looper)}
-     * for more detail on how to use this method.
+     * @param listener The listener
+     *
+     * @return A identifying string
+     */
+    private static String getListenerIdentifier(@NonNull Object listener) {
+        return listener.getClass().getName()
+                + '@'
+                + Integer.toHexString(System.identityHashCode(listener));
+    }
+
+    /**
+     * Asynchronously returns a single current location fix. This may activate sensors in order to
+     * compute a new location, unlike {@link #getLastKnownLocation(String)}, which will only return
+     * a cached fix if available. The given callback will be invoked once and only once, either with
+     * a valid location fix or with a null location fix if the provider was unable to generate a
+     * valid location.
+     *
+     * <p>A client may supply an optional {@link CancellationSignal}. If this is used to cancel the
+     * operation, no callback should be expected after the cancellation.
+     *
+     * <p>This method may return locations from the very recent past (on the order of several
+     * seconds), but will never return older locations (for example, several minutes old or older).
+     * Clients may rely upon the guarantee that if this method returns a location, it will represent
+     * the best estimation of the location of the device in the present moment.
+     *
+     * <p>Clients calling this method from the background may notice that the method fails to
+     * determine a valid location fix more often than while in the foreground. Background
+     * applications may be throttled in their location accesses to some degree.
+     *
+     * @param provider           the name of the provider with which to register
+     * @param cancellationSignal an optional signal that allows for cancelling this call
+     * @param executor           the callback will take place on this {@link Executor}
+     * @param consumer           the callback invoked with either a {@link Location} or null
+     *
+     * @throws IllegalArgumentException if provider is null or doesn't exist
+     * @throws IllegalArgumentException if executor is null
+     * @throws IllegalArgumentException if consumer is null
+     * @throws SecurityException        if no suitable permission is present
+     */
+    @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
+    public void getCurrentLocation(@NonNull String provider,
+            @Nullable CancellationSignal cancellationSignal,
+            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Location> consumer) {
+        getCurrentLocation(LocationRequest.createFromDeprecatedProvider(provider, 0, 0, true),
+                cancellationSignal, executor, consumer);
+    }
+
+    /**
+     * Asynchronously returns a single current location fix based on the given
+     * {@link LocationRequest}.
+     *
+     * <p>See {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)} for more
+     * information.
+     *
+     * @param locationRequest    the location request containing location parameters
+     * @param cancellationSignal an optional signal that allows for cancelling this call
+     * @param executor           the callback will take place on this {@link Executor}
+     * @param consumer           the callback invoked with either a {@link Location} or null
+     *
+     * @throws IllegalArgumentException if provider is null or doesn't exist
+     * @throws IllegalArgumentException if executor is null
+     * @throws IllegalArgumentException if consumer is null
+     * @throws SecurityException        if no suitable permission is present
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
+    public void getCurrentLocation(@NonNull LocationRequest locationRequest,
+            @Nullable CancellationSignal cancellationSignal,
+            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Location> consumer) {
+        LocationRequest currentLocationRequest = new LocationRequest(locationRequest)
+                .setNumUpdates(1).setExpireIn(GET_CURRENT_LOCATION_TIMEOUT_MS);
+
+        GetCurrentLocationTransport listenerTransport = new GetCurrentLocationTransport(executor,
+                consumer);
+
+        if (cancellationSignal != null) {
+            cancellationSignal.throwIfCanceled();
+        }
+
+        ICancellationSignal remoteCancellationSignal = CancellationSignal.createTransport();
+
+        try {
+            if (mService.getCurrentLocation(currentLocationRequest, remoteCancellationSignal,
+                    listenerTransport, mContext.getPackageName(),
+                    getListenerIdentifier(consumer))) {
+                listenerTransport.register(mContext.getSystemService(AlarmManager.class),
+                        remoteCancellationSignal);
+                if (cancellationSignal != null) {
+                    cancellationSignal.setOnCancelListener(listenerTransport::cancel);
+                }
+            } else {
+                listenerTransport.fail();
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Register for a single location update using the named provider and a callback.
+     *
+     * <p>See {@link #requestLocationUpdates(String, long, float, LocationListener, Looper)} for
+     * more detail on how to use this method.
      *
      * @param provider the name of the provider with which to register
-     * @param listener a {@link LocationListener} whose
-     * {@link LocationListener#onLocationChanged} method will be called when
-     * the location update is available
-     * @param looper a Looper object whose message queue will be used to
-     * implement the callback mechanism, or null to make callbacks on the calling
-     * thread
+     * @param listener the listener to receive location updates
+     * @param looper   the looper handling listener callbacks, or null to use the looper of the
+     *                 calling thread
      *
      * @throws IllegalArgumentException if provider is null or doesn't exist
      * @throws IllegalArgumentException if listener is null
-     * @throws SecurityException if no suitable permission is present
-     * @deprecated This method can drain much more battery than expected if it is not possible to
-     * calculate location. Prefer any of the requestLocationUpdates() methods which require explicit
-     * removal.
+     * @throws SecurityException        if no suitable permission is present
+     * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
+     * instead as it does not carry a risk of extreme battery drain.
      */
     @Deprecated
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
@@ -576,27 +686,21 @@
     }
 
     /**
-     * Register for a single location update using a Criteria and
-     * a callback.
+     * Register for a single location update using a Criteria and a callback.
      *
-     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
-     * for more detail on how to use this method.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} for more detail
+     * on how to use this method.
      *
-     * @param criteria contains parameters for the location manager to choose the
-     * appropriate provider and parameters to compute the location
-     * @param listener a {@link LocationListener} whose
-     * {@link LocationListener#onLocationChanged} method will be called when
-     * the location update is available
-     * @param looper a Looper object whose message queue will be used to
-     * implement the callback mechanism, or null to make callbacks on the calling
-     * thread
+     * @param criteria contains parameters to choose the appropriate provider for location updates
+     * @param listener the listener to receive location updates
+     * @param looper   the looper handling listener callbacks, or null to use the looper of the
+     *                 calling thread
      *
      * @throws IllegalArgumentException if criteria is null
      * @throws IllegalArgumentException if listener is null
-     * @throws SecurityException if no suitable permission is present
-     * @deprecated This method can drain much more battery than expected if it is not possible to
-     * calculate location. Prefer any of the requestLocationUpdates() methods which require explicit
-     * removal.
+     * @throws SecurityException        if no suitable permission is present
+     * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
+     * instead as it does not carry a risk of extreme battery drain.
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void requestSingleUpdate(
@@ -614,54 +718,54 @@
     /**
      * Register for a single location update using a named provider and pending intent.
      *
-     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
-     * for more detail on how to use this method.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} for more detail
+     * on how to use this method.
      *
-     * @param provider the name of the provider with which to register
-     * @param intent a {@link PendingIntent} to be sent for the location update
+     * @param provider      the name of the provider with which to register
+     * @param pendingIntent the pending intent to send location updates
      *
      * @throws IllegalArgumentException if provider is null or doesn't exist
      * @throws IllegalArgumentException if intent is null
-     * @throws SecurityException if no suitable permission is present
-     * @deprecated This method can drain much more battery than expected if it is not possible to
-     * calculate location. Prefer any of the requestLocationUpdates() methods which require explicit
-     * removal.
+     * @throws SecurityException        if no suitable permission is present
+     * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
+     * instead as it does not carry a risk of extreme battery drain.
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestSingleUpdate(@NonNull String provider, @NonNull PendingIntent intent) {
+    public void requestSingleUpdate(@NonNull String provider,
+            @NonNull PendingIntent pendingIntent) {
         Preconditions.checkArgument(provider != null, "invalid null provider");
-        checkPendingIntent(intent);
+        checkPendingIntent(pendingIntent);
 
         LocationRequest request = LocationRequest.createFromDeprecatedProvider(
                 provider, 0, 0, true);
-        requestLocationUpdates(request, intent);
+        requestLocationUpdates(request, pendingIntent);
     }
 
     /**
      * Register for a single location update using a Criteria and pending intent.
      *
-     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
-     * for more detail on how to use this method.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} for more detail
+     * on how to use this method.
      *
-     * @param criteria contains parameters for the location manager to choose the
-     * appropriate provider and parameters to compute the location
-     * @param intent a {@link PendingIntent} to be sent for the location update
+     * @param criteria      contains parameters to choose the appropriate provider for location
+     *                      updates
+     * @param pendingIntent the pending intent to send location updates
      *
      * @throws IllegalArgumentException if provider is null or doesn't exist
      * @throws IllegalArgumentException if intent is null
-     * @throws SecurityException if no suitable permission is present
-     * @deprecated This method can drain much more battery than expected if it is not possible to
-     * calculate location. Prefer any of the requestLocationUpdates() methods which require explicit
-     * removal.
+     * @throws SecurityException        if no suitable permission is present
+     * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
+     * instead as it does not carry a risk of extreme battery drain.
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestSingleUpdate(@NonNull Criteria criteria, @NonNull PendingIntent intent) {
+    public void requestSingleUpdate(@NonNull Criteria criteria,
+            @NonNull PendingIntent pendingIntent) {
         Preconditions.checkArgument(criteria != null, "invalid null criteria");
-        checkPendingIntent(intent);
+        checkPendingIntent(pendingIntent);
 
         LocationRequest request = LocationRequest.createFromDeprecatedCriteria(
                 criteria, 0, 0, true);
-        requestLocationUpdates(request, intent);
+        requestLocationUpdates(request, pendingIntent);
     }
 
     /**
@@ -981,7 +1085,7 @@
             boolean registered = false;
             try {
                 mService.requestLocationUpdates(locationRequest, transport, null,
-                        mContext.getPackageName());
+                        mContext.getPackageName(), getListenerIdentifier(listener));
                 registered = true;
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
@@ -1026,7 +1130,7 @@
 
         try {
             mService.requestLocationUpdates(locationRequest, null, pendingIntent,
-                    mContext.getPackageName());
+                    mContext.getPackageName(), getListenerIdentifier(pendingIntent));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1235,6 +1339,24 @@
     }
 
     /**
+     * Returns a list of packages associated with the given provider,
+     * and an empty list if no package is associated with the provider.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
+    @Nullable
+    public List<String> getProviderPackages(@NonNull String provider) {
+        try {
+            return mService.getProviderPackages(provider);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+            return Collections.emptyList();
+        }
+    }
+
+    /**
      * Sends additional commands to a location provider. Can be used to support provider specific
      * extensions to the Location Manager API.
      *
@@ -1471,7 +1593,8 @@
         Geofence fence = Geofence.createCircle(latitude, longitude, radius);
         LocationRequest request = new LocationRequest().setExpireIn(expiration);
         try {
-            mService.requestGeofence(request, fence, intent, mContext.getPackageName());
+            mService.requestGeofence(request, fence, intent, mContext.getPackageName(),
+                    getListenerIdentifier(intent));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1548,7 +1671,8 @@
         Preconditions.checkArgument(fence != null, "invalid null geofence");
 
         try {
-            mService.requestGeofence(request, fence, intent, mContext.getPackageName());
+            mService.requestGeofence(request, fence, intent, mContext.getPackageName(),
+                    getListenerIdentifier(intent));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1762,6 +1886,7 @@
      * @param handler  a handler with a looper that the callback runs on
      * @return true if the listener was successfully added
      *
+     * @throws IllegalArgumentException if callback is null
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
@@ -1781,10 +1906,12 @@
     /**
      * Registers a GNSS status callback.
      *
-     * @param callback GNSS status callback object to register
      * @param executor the executor that the callback runs on
+     * @param callback GNSS status callback object to register
      * @return true if the listener was successfully added
      *
+     * @throws IllegalArgumentException if executor is null
+     * @throws IllegalArgumentException if callback is null
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
@@ -1853,6 +1980,8 @@
      * @param listener a {@link OnNmeaMessageListener} object to register
      * @param handler  a handler with the looper that the listener runs on.
      * @return true if the listener was successfully added
+     *
+     * @throws IllegalArgumentException if listener is null
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
@@ -1874,6 +2003,9 @@
      * @param listener a {@link OnNmeaMessageListener} object to register
      * @param executor the {@link Executor} that the listener runs on.
      * @return true if the listener was successfully added
+     *
+     * @throws IllegalArgumentException if executor is null
+     * @throws IllegalArgumentException if listener is null
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
@@ -1925,7 +2057,7 @@
     public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {}
 
     /**
-     * Registers a GPS Measurement callback.
+     * Registers a GPS Measurement callback which will run on a binder thread.
      *
      * @param callback a {@link GnssMeasurementsEvent.Callback} object to register.
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
@@ -1937,7 +2069,7 @@
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean registerGnssMeasurementsCallback(
             @NonNull GnssMeasurementsEvent.Callback callback) {
-        return registerGnssMeasurementsCallback(callback, null);
+        return registerGnssMeasurementsCallback(Runnable::run, callback);
     }
 
     /**
@@ -1946,6 +2078,9 @@
      * @param callback a {@link GnssMeasurementsEvent.Callback} object to register.
      * @param handler  the handler that the callback runs on.
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+     *
+     * @throws IllegalArgumentException if callback is null
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean registerGnssMeasurementsCallback(
@@ -1966,6 +2101,10 @@
      * @param callback a {@link GnssMeasurementsEvent.Callback} object to register.
      * @param executor the executor that the callback runs on.
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+     *
+     * @throws IllegalArgumentException if executor is null
+     * @throws IllegalArgumentException if callback is null
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean registerGnssMeasurementsCallback(
@@ -1983,6 +2122,9 @@
      *
      * @param measurementCorrections a {@link GnssMeasurementCorrections} object with the GNSS
      *     measurement corrections to be injected into the GNSS chipset.
+     *
+     * @throws IllegalArgumentException if measurementCorrections is null
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      * @hide
      */
     @SystemApi
@@ -2057,6 +2199,9 @@
      * @param callback a {@link GnssNavigationMessage.Callback} object to register.
      * @param handler  the handler that the callback runs on.
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+     *
+     * @throws IllegalArgumentException if callback is null
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean registerGnssNavigationMessageCallback(
@@ -2078,6 +2223,10 @@
      * @param callback a {@link GnssNavigationMessage.Callback} object to register.
      * @param executor the looper that the callback runs on.
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+     *
+     * @throws IllegalArgumentException if executor is null
+     * @throws IllegalArgumentException if callback is null
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean registerGnssNavigationMessageCallback(
@@ -2232,6 +2381,127 @@
         }
     }
 
+    private static class GetCurrentLocationTransport extends ILocationListener.Stub implements
+            AlarmManager.OnAlarmListener {
+
+        @GuardedBy("this")
+        @Nullable
+        private Executor mExecutor;
+
+        @GuardedBy("this")
+        @Nullable
+        private Consumer<Location> mConsumer;
+
+        @GuardedBy("this")
+        @Nullable
+        private AlarmManager mAlarmManager;
+
+        @GuardedBy("this")
+        @Nullable
+        private ICancellationSignal mRemoteCancellationSignal;
+
+        private GetCurrentLocationTransport(Executor executor, Consumer<Location> consumer) {
+            Preconditions.checkArgument(executor != null, "illegal null executor");
+            Preconditions.checkArgument(consumer != null, "illegal null consumer");
+            mExecutor = executor;
+            mConsumer = consumer;
+            mAlarmManager = null;
+            mRemoteCancellationSignal = null;
+        }
+
+        public synchronized void register(AlarmManager alarmManager,
+                ICancellationSignal remoteCancellationSignal) {
+            if (mConsumer == null) {
+                return;
+            }
+
+            mAlarmManager = alarmManager;
+            mAlarmManager.set(
+                    ELAPSED_REALTIME,
+                    SystemClock.elapsedRealtime() + GET_CURRENT_LOCATION_TIMEOUT_MS,
+                    "GetCurrentLocation",
+                    this,
+                    null);
+
+            mRemoteCancellationSignal = remoteCancellationSignal;
+        }
+
+        public synchronized void cancel() {
+            mExecutor = null;
+            mConsumer = null;
+
+            if (mAlarmManager != null) {
+                mAlarmManager.cancel(this);
+                mAlarmManager = null;
+            }
+
+            if (mRemoteCancellationSignal != null) {
+                try {
+                    mRemoteCancellationSignal.cancel();
+                } catch (RemoteException e) {
+                    // ignore
+                }
+                mRemoteCancellationSignal = null;
+            }
+        }
+
+        public void fail() {
+            deliverResult(null);
+        }
+
+        @Override
+        public void onAlarm() {
+            synchronized (this) {
+                // save ourselves a pointless x-process call to cancel the alarm
+                mAlarmManager = null;
+            }
+
+            deliverResult(null);
+        }
+
+        @Override
+        public void onLocationChanged(Location location) {
+            synchronized (this) {
+                // save ourselves a pointless x-process call to cancel the location request
+                mRemoteCancellationSignal = null;
+            }
+
+            deliverResult(location);
+        }
+
+        @Override
+        public void onStatusChanged(String provider, int status, Bundle extras) {}
+
+        @Override
+        public void onProviderEnabled(String provider) {}
+
+        @Override
+        public void onProviderDisabled(String provider) {
+            // in the event of the provider being disabled it is unlikely that we will get further
+            // locations, so fail early so the client isn't left waiting hopelessly
+            deliverResult(null);
+        }
+
+        private synchronized void deliverResult(@Nullable Location location) {
+            if (mExecutor == null) {
+                return;
+            }
+
+            mExecutor.execute(() -> {
+                Consumer<Location> consumer;
+                synchronized (GetCurrentLocationTransport.this) {
+                    if (mConsumer == null) {
+                        return;
+                    }
+                    consumer = mConsumer;
+                    cancel();
+                }
+
+                consumer.accept(location);
+            });
+        }
+    }
+
     private class LocationListenerTransport extends ILocationListener.Stub {
 
         private final LocationListener mListener;
@@ -2538,7 +2808,7 @@
 
             mListenerTransport = new GnssMeasurementsListener();
             return mService.addGnssMeasurementsListener(mListenerTransport,
-                    mContext.getPackageName());
+                    mContext.getPackageName(), "gnss measurement callback");
         }
 
         @Override
@@ -2574,7 +2844,7 @@
 
             mListenerTransport = new GnssNavigationMessageListener();
             return mService.addGnssNavigationMessageListener(mListenerTransport,
-                    mContext.getPackageName());
+                    mContext.getPackageName(), "gnss navigation callback");
         }
 
         @Override
@@ -2609,7 +2879,8 @@
             Preconditions.checkState(mListenerTransport == null);
 
             mListenerTransport = new BatchedLocationCallback();
-            return mService.addGnssBatchingCallback(mListenerTransport, mContext.getPackageName());
+            return mService.addGnssBatchingCallback(mListenerTransport, mContext.getPackageName(),
+                     "batched location callback");
         }
 
         @Override
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 65d3ffc..ac5a9f8 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -670,7 +670,7 @@
                     mUsage = usage;
                     break;
                 default:
-                    mUsage = USAGE_UNKNOWN;
+                    throw new IllegalArgumentException("Invalid usage " + usage);
             }
             return this;
         }
@@ -696,7 +696,7 @@
                     mContentType = contentType;
                     break;
                 default:
-                    mContentType = CONTENT_TYPE_UNKNOWN;
+                    throw new IllegalArgumentException("Invalid content type " + contentType);
             }
             return this;
         }
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 5341d07..33ddfa7 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -2776,7 +2776,7 @@
         updateImageSizeValues(in, IFD_TYPE_THUMBNAIL);
 
         // Check if each image data is in valid position.
-        validateImages(in);
+        validateImages();
 
         if (mMimeType == IMAGE_TYPE_PEF) {
             // PEF files contain a MakerNote data, which contains the data for ColorSpace tag.
@@ -3143,8 +3143,11 @@
         // 2.1. Integers and byte order
         in.setByteOrder(ByteOrder.BIG_ENDIAN);
 
+        int bytesRead = 0;
+
         // Skip the signature bytes
         in.seek(PNG_SIGNATURE.length);
+        bytesRead += PNG_SIGNATURE.length;
 
         try {
             while (true) {
@@ -3159,12 +3162,14 @@
                 // See PNG (Portable Network Graphics) Specification, Version 1.2,
                 // 3.2. Chunk layout
                 int length = in.readInt();
+                bytesRead += 4;
 
                 byte[] type = new byte[PNG_CHUNK_LENGTH_BYTE_LENGTH];
                 if (in.read(type) != type.length) {
                     throw new IOException("Encountered invalid length while parsing PNG chunk"
                             + "type");
                 }
+                bytesRead += PNG_CHUNK_LENGTH_BYTE_LENGTH;
 
                 if (Arrays.equals(type, PNG_CHUNK_TYPE_IEND)) {
                     // IEND marks the end of the image.
@@ -3177,12 +3182,17 @@
                                 + "type: " + byteArrayToHexString(type));
                     }
                     readExifSegment(data, IFD_TYPE_PRIMARY);
+
+                    validateImages();
                     break;
                 } else {
                     // Skip to next chunk
                     in.skipBytes(length + PNG_CHUNK_CRC_BYTE_LENGTH);
+                    bytesRead += length + PNG_CHUNK_CRC_BYTE_LENGTH;
                 }
             }
+            // Save offset values for handleThumbnailFromJfif() function
+            mExifOffset = bytesRead;
         } catch (EOFException e) {
             // Should not reach here. Will only reach here if the file is corrupted or
             // does not follow the PNG specifications
@@ -3675,7 +3685,7 @@
             int thumbnailLength = jpegInterchangeFormatLengthAttribute.getIntValue(mExifByteOrder);
 
             if (mMimeType == IMAGE_TYPE_JPEG || mMimeType == IMAGE_TYPE_RAF
-                    || mMimeType == IMAGE_TYPE_RW2) {
+                    || mMimeType == IMAGE_TYPE_RW2 || mMimeType == IMAGE_TYPE_PNG) {
                 thumbnailOffset += mExifOffset;
             } else if (mMimeType == IMAGE_TYPE_ORF) {
                 // Update offset value since RAF files have IFD data preceding MakerNote data.
@@ -3819,12 +3829,13 @@
     }
 
     // Validate primary, preview, thumbnail image data by comparing image size
-    private void validateImages(InputStream in) throws IOException {
+    private void validateImages() throws IOException {
         // Swap images based on size (primary > preview > thumbnail)
         swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_PREVIEW);
         swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_THUMBNAIL);
         swapBasedOnImageSize(IFD_TYPE_PREVIEW, IFD_TYPE_THUMBNAIL);
 
+        // TODO (b/142296453): Revise image width/height setting logic
         // Check if image has PixelXDimension/PixelYDimension tags, which contain valid image
         // sizes, excluding padding at the right end or bottom end of the image to make sure that
         // the values are multiples of 64. See JEITA CP-3451C Table 5 and Section 4.8.1. B.
diff --git a/media/java/android/media/IMediaRoute2Provider.aidl b/media/java/android/media/IMediaRoute2Provider.aidl
index f132cef..66764c7 100644
--- a/media/java/android/media/IMediaRoute2Provider.aidl
+++ b/media/java/android/media/IMediaRoute2Provider.aidl
@@ -27,4 +27,6 @@
     void selectRoute(String packageName, String id);
     void unselectRoute(String packageName, String id);
     void notifyControlRequestSent(String id, in Intent request);
+    void requestSetVolume(String id, int volume);
+    void requestUpdateVolume(String id, int delta);
 }
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 81213b9..7b7a34e 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -46,6 +46,8 @@
     void registerClient2(IMediaRouter2Client client, String packageName);
     void unregisterClient2(IMediaRouter2Client client);
     void sendControlRequest(IMediaRouter2Client client, in MediaRoute2Info route, in Intent request);
+    void requestSetVolume2(IMediaRouter2Client client, in MediaRoute2Info route, int volume);
+    void requestUpdateVolume2(IMediaRouter2Client client, in MediaRoute2Info route, int direction);
     /**
      * Changes the selected route of the client.
      *
@@ -66,4 +68,9 @@
      */
     void selectClientRoute2(IMediaRouter2Manager manager, String packageName,
             in @nullable MediaRoute2Info route);
+
+    void requestSetVolume2Manager(IMediaRouter2Manager manager,
+            in MediaRoute2Info route, int volume);
+    void requestUpdateVolume2Manager(IMediaRouter2Manager manager,
+            in MediaRoute2Info route, int direction);
 }
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
index b12e647..e85b3ff9 100644
--- a/media/java/android/media/JetPlayer.java
+++ b/media/java/android/media/JetPlayer.java
@@ -17,18 +17,17 @@
 package android.media;
 
 
-import java.io.FileDescriptor;
-import java.lang.ref.WeakReference;
-import java.lang.CloneNotSupportedException;
-
 import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetFileDescriptor;
-import android.os.Looper;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
 
+import java.io.FileDescriptor;
+import java.lang.ref.WeakReference;
+
 /**
  * JetPlayer provides access to JET content playback and control.
  * 
@@ -120,6 +119,9 @@
     
     private static JetPlayer singletonRef;
     
+    static {
+        System.loadLibrary("media_jni");
+    }
     
     //--------------------------------
     // Used exclusively by native code
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 26e7936..91d644b 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -21,6 +21,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
@@ -3750,8 +3751,11 @@
         public static final int DolbyVisionProfileDvheStn = 0x20;
         public static final int DolbyVisionProfileDvheDth = 0x40;
         public static final int DolbyVisionProfileDvheDtb = 0x80;
-        public static final int DolbyVisionProfileDvheSt = 0x100;
-        public static final int DolbyVisionProfileDvavSe = 0x200;
+        public static final int DolbyVisionProfileDvheSt  = 0x100;
+        public static final int DolbyVisionProfileDvavSe  = 0x200;
+        /** Dolby Vision AV1 profile */
+        @SuppressLint("AllUpper")
+        public static final int DolbyVisionProfileDvav110 = 0x400;
 
         public static final int DolbyVisionLevelHd24    = 0x1;
         public static final int DolbyVisionLevelHd30    = 0x2;
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 7ed431d..cc5ddeb 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -224,7 +224,7 @@
      * @return The meta data value associate with the given keyCode on success;
      * null on failure.
      */
-    public native String extractMetadata(int keyCode);
+    public native @Nullable String extractMetadata(int keyCode);
 
     /**
      * This method is similar to {@link #getFrameAtTime(long, int, BitmapParams)}
@@ -255,7 +255,7 @@
      *
      * @see {@link #getFrameAtTime(long, int, BitmapParams)}
      */
-    public Bitmap getFrameAtTime(long timeUs, @Option int option) {
+    public @Nullable Bitmap getFrameAtTime(long timeUs, @Option int option) {
         if (option < OPTION_PREVIOUS_SYNC ||
             option > OPTION_CLOSEST) {
             throw new IllegalArgumentException("Unsupported option: " + option);
@@ -301,7 +301,7 @@
      *
      * @see {@link #getFrameAtTime(long, int)}
      */
-    public Bitmap getFrameAtTime(
+    public @Nullable Bitmap getFrameAtTime(
             long timeUs, @Option int option, @NonNull BitmapParams params) {
         if (option < OPTION_PREVIOUS_SYNC ||
             option > OPTION_CLOSEST) {
@@ -343,7 +343,7 @@
      *         is less than or equal to 0.
      * @see {@link #getScaledFrameAtTime(long, int, int, int, BitmapParams)}
      */
-    public Bitmap getScaledFrameAtTime(
+    public @Nullable Bitmap getScaledFrameAtTime(
             long timeUs, @Option int option, int dstWidth, int dstHeight) {
         validate(option, dstWidth, dstHeight);
         return _getFrameAtTime(timeUs, option, dstWidth, dstHeight, null);
@@ -388,7 +388,7 @@
      *         is less than or equal to 0.
      * @see {@link #getScaledFrameAtTime(long, int, int, int)}
      */
-    public Bitmap getScaledFrameAtTime(long timeUs, @Option int option,
+    public @Nullable Bitmap getScaledFrameAtTime(long timeUs, @Option int option,
             int dstWidth, int dstHeight, @NonNull BitmapParams params) {
         validate(option, dstWidth, dstHeight);
         return _getFrameAtTime(timeUs, option, dstWidth, dstHeight, params);
@@ -430,7 +430,7 @@
      *
      * @see #getFrameAtTime(long, int)
      */
-    public Bitmap getFrameAtTime(long timeUs) {
+    public @Nullable Bitmap getFrameAtTime(long timeUs) {
         return getFrameAtTime(timeUs, OPTION_CLOSEST_SYNC);
     }
 
@@ -452,7 +452,7 @@
      * @see #getFrameAtTime(long)
      * @see #getFrameAtTime(long, int)
      */
-    public Bitmap getFrameAtTime() {
+    public @Nullable Bitmap getFrameAtTime() {
         return _getFrameAtTime(
                 -1, OPTION_CLOSEST_SYNC, -1 /*dst_width*/, -1 /*dst_height*/, null);
     }
@@ -528,7 +528,7 @@
      * @see #getFramesAtIndex(int, int, BitmapParams)
      * @see #getFramesAtIndex(int, int)
      */
-    public Bitmap getFrameAtIndex(int frameIndex, @NonNull BitmapParams params) {
+    public @Nullable Bitmap getFrameAtIndex(int frameIndex, @NonNull BitmapParams params) {
         List<Bitmap> bitmaps = getFramesAtIndex(frameIndex, 1, params);
         return bitmaps.get(0);
     }
@@ -550,7 +550,7 @@
      * @see #getFramesAtIndex(int, int, BitmapParams)
      * @see #getFramesAtIndex(int, int)
      */
-    public Bitmap getFrameAtIndex(int frameIndex) {
+    public @Nullable Bitmap getFrameAtIndex(int frameIndex) {
         List<Bitmap> bitmaps = getFramesAtIndex(frameIndex, 1);
         return bitmaps.get(0);
     }
@@ -653,7 +653,7 @@
      * @see #getPrimaryImage(BitmapParams)
      * @see #getPrimaryImage()
      */
-    public Bitmap getImageAtIndex(int imageIndex, @NonNull BitmapParams params) {
+    public @Nullable Bitmap getImageAtIndex(int imageIndex, @NonNull BitmapParams params) {
         return getImageAtIndexInternal(imageIndex, params);
     }
 
@@ -691,7 +691,7 @@
      * @see #getPrimaryImage(BitmapParams)
      * @see #getPrimaryImage()
      */
-    public Bitmap getImageAtIndex(int imageIndex) {
+    public @Nullable Bitmap getImageAtIndex(int imageIndex) {
         return getImageAtIndexInternal(imageIndex, null);
     }
 
@@ -713,7 +713,7 @@
      * @see #getImageAtIndex(int)
      * @see #getPrimaryImage()
      */
-    public Bitmap getPrimaryImage(@NonNull BitmapParams params) {
+    public @Nullable Bitmap getPrimaryImage(@NonNull BitmapParams params) {
         return getImageAtIndexInternal(-1, params);
     }
 
@@ -729,7 +729,7 @@
      * @see #getImageAtIndex(int)
      * @see #getPrimaryImage(BitmapParams)
      */
-    public Bitmap getPrimaryImage() {
+    public @Nullable Bitmap getPrimaryImage() {
         return getImageAtIndexInternal(-1, null);
     }
 
@@ -755,7 +755,7 @@
      *
      * @return null if no such graphic is found.
      */
-    public byte[] getEmbeddedPicture() {
+    public @Nullable byte[] getEmbeddedPicture() {
         return getEmbeddedPicture(EMBEDDED_PICTURE_TYPE_ANY);
     }
 
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index abd774d..59bd96f 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -79,6 +79,8 @@
     @Nullable
     final Bundle mExtras;
 
+    private final String mUniqueId;
+
     MediaRoute2Info(@NonNull Builder builder) {
         mId = builder.mId;
         mProviderId = builder.mProviderId;
@@ -90,6 +92,7 @@
         mVolumeMax = builder.mVolumeMax;
         mVolumeHandling = builder.mVolumeHandling;
         mExtras = builder.mExtras;
+        mUniqueId = createUniqueId();
     }
 
     MediaRoute2Info(@NonNull Parcel in) {
@@ -103,6 +106,15 @@
         mVolumeMax = in.readInt();
         mVolumeHandling = in.readInt();
         mExtras = in.readBundle();
+        mUniqueId = createUniqueId();
+    }
+
+    private String createUniqueId() {
+        String uniqueId = null;
+        if (mProviderId != null) {
+            uniqueId = mProviderId + ":" + mId;
+        }
+        return uniqueId;
     }
 
     /**
@@ -147,13 +159,33 @@
         return Objects.hash(mId, mName, mDescription, mSupportedCategories);
     }
 
+    /**
+     * Gets the id of the route.
+     * Use {@link #getUniqueId()} if you need a unique identifier.
+     *
+     * @see #getUniqueId()
+     */
     @NonNull
     public String getId() {
         return mId;
     }
 
     /**
-     * Gets the provider id of the route.
+     * Gets the unique id of the route. A route obtained from
+     * {@link com.android.server.media.MediaRouterService} always has a unique id.
+     *
+     * @return unique id of the route or null if it has no unique id.
+     */
+    @Nullable
+    public String getUniqueId() {
+        return mUniqueId;
+    }
+
+    /**
+     * Gets the provider id of the route. It is assigned automatically by
+     * {@link com.android.server.media.MediaRouterService}.
+     *
+     * @return provider id of the route or null if it's not set.
      * @hide
      */
     @Nullable
@@ -337,7 +369,7 @@
         @NonNull
         public Builder setProviderId(@NonNull String providerId) {
             if (TextUtils.isEmpty(providerId)) {
-                throw new IllegalArgumentException("id must not be null or empty");
+                throw new IllegalArgumentException("providerId must not be null or empty");
             }
             mProviderId = providerId;
             return this;
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index e8e0f82..5f5d200 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -30,7 +30,7 @@
  * @hide
  */
 public abstract class MediaRoute2ProviderService extends Service {
-    private static final String TAG = "MediaRouteProviderSrv";
+    private static final String TAG = "MR2ProviderService";
 
     public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService";
 
@@ -81,6 +81,20 @@
     public abstract void onControlRequest(String routeId, Intent request);
 
     /**
+     * Called when requestSetVolume is called on a route of the provider
+     * @param routeId the id of the route
+     * @param volume the target volume
+     */
+    public abstract void onSetVolume(String routeId, int volume);
+
+    /**
+     * Called when requestUpdateVolume is called on a route of the provider
+     * @param routeId id of the route
+     * @param delta the delta to add to the current volume
+     */
+    public abstract void onUpdateVolume(String routeId, int delta);
+
+    /**
      * Updates provider info and publishes routes
      */
     public final void setProviderInfo(MediaRoute2ProviderInfo info) {
@@ -130,5 +144,17 @@
             mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onControlRequest,
                     MediaRoute2ProviderService.this, id, request));
         }
+
+        @Override
+        public void requestSetVolume(String id, int volume) {
+            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetVolume,
+                    MediaRoute2ProviderService.this, id, volume));
+        }
+
+        @Override
+        public void requestUpdateVolume(String id, int delta) {
+            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onUpdateVolume,
+                    MediaRoute2ProviderService.this, id, delta));
+        }
     }
 }
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index ed35ef6..b52e2d6 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -44,7 +44,7 @@
  * @hide
  */
 public class MediaRouter2 {
-    private static final String TAG = "MediaRouter";
+    private static final String TAG = "MR2";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final Object sLock = new Object();
 
@@ -54,7 +54,8 @@
     private Context mContext;
     private final IMediaRouterService mMediaRouterService;
 
-    private CopyOnWriteArrayList<CallbackRecord> mCallbackRecords = new CopyOnWriteArrayList<>();
+    private final CopyOnWriteArrayList<CallbackRecord> mCallbackRecords =
+            new CopyOnWriteArrayList<>();
     @GuardedBy("sLock")
     private List<String> mControlCategories = Collections.emptyList();
     @GuardedBy("sLock")
@@ -265,6 +266,54 @@
         }
     }
 
+    /**
+     * Requests a volume change for the route asynchronously.
+     * <p>
+     * It may have no effect if the route is currently not selected.
+     * </p>
+     *
+     * @param volume The new volume value between 0 and {@link MediaRoute2Info#getVolumeMax}.
+     */
+    public void requestSetVolume(@NonNull MediaRoute2Info route, int volume) {
+        Objects.requireNonNull(route, "route must not be null");
+
+        Client client;
+        synchronized (sLock) {
+            client = mClient;
+        }
+        if (client != null) {
+            try {
+                mMediaRouterService.requestSetVolume2(client, route, volume);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "Unable to send control request.", ex);
+            }
+        }
+    }
+
+    /**
+     * Requests an incremental volume update  for the route asynchronously.
+     * <p>
+     * It may have no effect if the route is currently not selected.
+     * </p>
+     *
+     * @param delta The delta to add to the current volume.
+     */
+    public void requestUpdateVolume(@NonNull MediaRoute2Info route, int delta) {
+        Objects.requireNonNull(route, "route must not be null");
+
+        Client client;
+        synchronized (sLock) {
+            client = mClient;
+        }
+        if (client != null) {
+            try {
+                mMediaRouterService.requestUpdateVolume2(client, route, delta);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "Unable to send control request.", ex);
+            }
+        }
+    }
+
     @GuardedBy("mCallbackRecords")
     private int findCallbackRecordIndexLocked(Callback callback) {
         final int count = mCallbackRecords.size();
@@ -310,6 +359,7 @@
             List<MediaRoute2Info> outRoutes) {
         if (provider == null || !provider.isValid()) {
             Log.w(TAG, "Ignoring invalid provider : " + provider);
+            return;
         }
 
         final Collection<MediaRoute2Info> routes = provider.getRoutes();
@@ -321,10 +371,21 @@
             if (!route.supportsControlCategory(controlCategories)) {
                 continue;
             }
+            MediaRoute2Info preRoute = findRouteById(route.getId());
+            if (!route.equals(preRoute)) {
+                notifyRouteChanged(route);
+            }
             outRoutes.add(route);
         }
     }
 
+    MediaRoute2Info findRouteById(String id) {
+        for (MediaRoute2Info route : mRoutes) {
+            if (route.getId().equals(id)) return route;
+        }
+        return null;
+    }
+
     void notifyRouteListChanged(List<MediaRoute2Info> routes) {
         for (CallbackRecord record: mCallbackRecords) {
             record.mExecutor.execute(
@@ -332,10 +393,18 @@
         }
     }
 
+    void notifyRouteChanged(MediaRoute2Info route) {
+        for (CallbackRecord record: mCallbackRecords) {
+            record.mExecutor.execute(
+                    () -> record.mCallback.onRouteChanged(route));
+        }
+    }
+
     /**
      * Interface for receiving events about media routing changes.
      */
     public static class Callback {
+        //TODO: clean up these callbacks
         /**
          * Called when a route is added.
          */
@@ -369,7 +438,7 @@
         void notifyRoutes() {
             final List<MediaRoute2Info> routes = mRoutes;
             // notify only when bound to media router service.
-            //TODO: Correct the condition when control category, default rotue, .. are finalized.
+            //TODO: Correct the condition when control category, default route, .. are finalized.
             if (routes.size() > 0) {
                 mExecutor.execute(() -> mCallback.onRoutesChanged(routes));
             }
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 0b64569..0d7b6ff 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -46,7 +46,7 @@
  * @hide
  */
 public class MediaRouter2Manager {
-    private static final String TAG = "MediaRouter2Manager";
+    private static final String TAG = "MR2Manager";
     private static final Object sLock = new Object();
 
     @GuardedBy("sLock")
@@ -234,6 +234,54 @@
         }
     }
 
+    /**
+     * Requests a volume change for the route asynchronously.
+     * <p>
+     * It may have no effect if the route is currently not selected.
+     * </p>
+     *
+     * @param volume The new volume value between 0 and {@link MediaRoute2Info#getVolumeMax}.
+     */
+    public void requestSetVolume(@NonNull MediaRoute2Info route, int volume) {
+        Objects.requireNonNull(route, "route must not be null");
+
+        Client client;
+        synchronized (sLock) {
+            client = mClient;
+        }
+        if (client != null) {
+            try {
+                mMediaRouterService.requestSetVolume2Manager(client, route, volume);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "Unable to send control request.", ex);
+            }
+        }
+    }
+
+    /**
+     * Requests an incremental volume update  for the route asynchronously.
+     * <p>
+     * It may have no effect if the route is currently not selected.
+     * </p>
+     *
+     * @param delta The delta to add to the current volume.
+     */
+    public void requestUpdateVolume(@NonNull MediaRoute2Info route, int delta) {
+        Objects.requireNonNull(route, "route must not be null");
+
+        Client client;
+        synchronized (sLock) {
+            client = mClient;
+        }
+        if (client != null) {
+            try {
+                mMediaRouterService.requestUpdateVolume2Manager(client, route, delta);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "Unable to send control request.", ex);
+            }
+        }
+    }
+
     int findProviderIndex(MediaRoute2ProviderInfo provider) {
         final int count = mProviders.size();
         for (int i = 0; i < count; i++) {
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 771628c..ca96c9a 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -17,106 +17,14 @@
 package android.media;
 
 import android.annotation.UnsupportedAppUsage;
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
-import android.content.SharedPreferences;
-import android.database.Cursor;
-import android.database.SQLException;
-import android.drm.DrmManagerClient;
-import android.graphics.BitmapFactory;
-import android.mtp.MtpConstants;
 import android.net.Uri;
 import android.os.Build;
-import android.os.Environment;
 import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.provider.MediaStore;
-import android.provider.MediaStore.Audio;
-import android.provider.MediaStore.Audio.Playlists;
-import android.provider.MediaStore.Files;
-import android.provider.MediaStore.Files.FileColumns;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.Video;
-import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
-import android.sax.Element;
-import android.sax.ElementListener;
-import android.sax.RootElement;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Xml;
-
-import dalvik.system.CloseGuard;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Locale;
-import java.util.TimeZone;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
- * Internal service helper that no-one should use directly.
- *
- * The way the scan currently works is:
- * - The Java MediaScannerService creates a MediaScanner (this class), and calls
- *   MediaScanner.scanDirectories on it.
- * - scanDirectories() calls the native processDirectory() for each of the specified directories.
- * - the processDirectory() JNI method wraps the provided mediascanner client in a native
- *   'MyMediaScannerClient' class, then calls processDirectory() on the native MediaScanner
- *   object (which got created when the Java MediaScanner was created).
- * - native MediaScanner.processDirectory() calls
- *   doProcessDirectory(), which recurses over the folder, and calls
- *   native MyMediaScannerClient.scanFile() for every file whose extension matches.
- * - native MyMediaScannerClient.scanFile() calls back on Java MediaScannerClient.scanFile,
- *   which calls doScanFile, which after some setup calls back down to native code, calling
- *   MediaScanner.processFile().
- * - MediaScanner.processFile() calls one of several methods, depending on the type of the
- *   file: parseMP3, parseMP4, parseMidi, parseOgg or parseWMA.
- * - each of these methods gets metadata key/value pairs from the file, and repeatedly
- *   calls native MyMediaScannerClient.handleStringTag, which calls back up to its Java
- *   counterparts in this file.
- * - Java handleStringTag() gathers the key/value pairs that it's interested in.
- * - once processFile returns and we're back in Java code in doScanFile(), it calls
- *   Java MyMediaScannerClient.endFile(), which takes all the data that's been
- *   gathered and inserts an entry in to the database.
- *
- * In summary:
- * Java MediaScannerService calls
- * Java MediaScanner scanDirectories, which calls
- * Java MediaScanner processDirectory (native method), which calls
- * native MediaScanner processDirectory, which calls
- * native MyMediaScannerClient scanFile, which calls
- * Java MyMediaScannerClient scanFile, which calls
- * Java MediaScannerClient doScanFile, which calls
- * Java MediaScanner processFile (native method), which calls
- * native MediaScanner processFile, which calls
- * native parseMP3, parseMP4, parseMidi, parseOgg or parseWMA, which calls
- * native MyMediaScanner handleStringTag, which calls
- * Java MyMediaScanner handleStringTag.
- * Once MediaScanner processFile returns, an entry is inserted in to the database.
- *
- * The MediaScanner class is not thread-safe, so it should only be used in a single threaded manner.
- *
- * {@hide}
- *
+ * @hide
  * @deprecated this media scanner has served faithfully for many years, but it's
  *             become tedious to test and maintain, mainly due to the way it
  *             weaves obscurely between managed and native code. It's been
@@ -125,1876 +33,182 @@
  */
 @Deprecated
 public class MediaScanner implements AutoCloseable {
-    static {
-        System.loadLibrary("media_jni");
-        native_init();
-    }
-
-    private final static String TAG = "MediaScanner";
-
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     private static final String[] FILES_PRESCAN_PROJECTION = new String[] {
-            Files.FileColumns._ID, // 0
-            Files.FileColumns.DATA, // 1
-            Files.FileColumns.FORMAT, // 2
-            Files.FileColumns.DATE_MODIFIED, // 3
-            Files.FileColumns.MEDIA_TYPE, // 4
     };
 
-    private static final String[] ID_PROJECTION = new String[] {
-            Files.FileColumns._ID,
-    };
-
-    private static final int FILES_PRESCAN_ID_COLUMN_INDEX = 0;
-    private static final int FILES_PRESCAN_PATH_COLUMN_INDEX = 1;
-    private static final int FILES_PRESCAN_FORMAT_COLUMN_INDEX = 2;
-    private static final int FILES_PRESCAN_DATE_MODIFIED_COLUMN_INDEX = 3;
-    private static final int FILES_PRESCAN_MEDIA_TYPE_COLUMN_INDEX = 4;
-
-    private static final String[] PLAYLIST_MEMBERS_PROJECTION = new String[] {
-            Audio.Playlists.Members.PLAYLIST_ID, // 0
-     };
-
-    private static final int ID_PLAYLISTS_COLUMN_INDEX = 0;
-    private static final int PATH_PLAYLISTS_COLUMN_INDEX = 1;
-    private static final int DATE_MODIFIED_PLAYLISTS_COLUMN_INDEX = 2;
-
-    private static final String RINGTONES_DIR = "/ringtones/";
-    private static final String NOTIFICATIONS_DIR = "/notifications/";
-    private static final String ALARMS_DIR = "/alarms/";
-    private static final String MUSIC_DIR = "/music/";
-    private static final String PODCASTS_DIR = "/podcasts/";
-    private static final String AUDIOBOOKS_DIR = "/audiobooks/";
-
-    public static final String SCANNED_BUILD_PREFS_NAME = "MediaScanBuild";
-    public static final String LAST_INTERNAL_SCAN_FINGERPRINT = "lastScanFingerprint";
-    private static final String SYSTEM_SOUNDS_DIR = Environment.getRootDirectory() + "/media/audio";
-    private static final String OEM_SOUNDS_DIR = Environment.getOemDirectory() + "/media/audio";
-    private static final String PRODUCT_SOUNDS_DIR = Environment.getProductDirectory() + "/media/audio";
-    private static String sLastInternalScanFingerprint;
-
-    private static final String[] ID3_GENRES = {
-        // ID3v1 Genres
-        "Blues",
-        "Classic Rock",
-        "Country",
-        "Dance",
-        "Disco",
-        "Funk",
-        "Grunge",
-        "Hip-Hop",
-        "Jazz",
-        "Metal",
-        "New Age",
-        "Oldies",
-        "Other",
-        "Pop",
-        "R&B",
-        "Rap",
-        "Reggae",
-        "Rock",
-        "Techno",
-        "Industrial",
-        "Alternative",
-        "Ska",
-        "Death Metal",
-        "Pranks",
-        "Soundtrack",
-        "Euro-Techno",
-        "Ambient",
-        "Trip-Hop",
-        "Vocal",
-        "Jazz+Funk",
-        "Fusion",
-        "Trance",
-        "Classical",
-        "Instrumental",
-        "Acid",
-        "House",
-        "Game",
-        "Sound Clip",
-        "Gospel",
-        "Noise",
-        "AlternRock",
-        "Bass",
-        "Soul",
-        "Punk",
-        "Space",
-        "Meditative",
-        "Instrumental Pop",
-        "Instrumental Rock",
-        "Ethnic",
-        "Gothic",
-        "Darkwave",
-        "Techno-Industrial",
-        "Electronic",
-        "Pop-Folk",
-        "Eurodance",
-        "Dream",
-        "Southern Rock",
-        "Comedy",
-        "Cult",
-        "Gangsta",
-        "Top 40",
-        "Christian Rap",
-        "Pop/Funk",
-        "Jungle",
-        "Native American",
-        "Cabaret",
-        "New Wave",
-        "Psychadelic",
-        "Rave",
-        "Showtunes",
-        "Trailer",
-        "Lo-Fi",
-        "Tribal",
-        "Acid Punk",
-        "Acid Jazz",
-        "Polka",
-        "Retro",
-        "Musical",
-        "Rock & Roll",
-        "Hard Rock",
-        // The following genres are Winamp extensions
-        "Folk",
-        "Folk-Rock",
-        "National Folk",
-        "Swing",
-        "Fast Fusion",
-        "Bebob",
-        "Latin",
-        "Revival",
-        "Celtic",
-        "Bluegrass",
-        "Avantgarde",
-        "Gothic Rock",
-        "Progressive Rock",
-        "Psychedelic Rock",
-        "Symphonic Rock",
-        "Slow Rock",
-        "Big Band",
-        "Chorus",
-        "Easy Listening",
-        "Acoustic",
-        "Humour",
-        "Speech",
-        "Chanson",
-        "Opera",
-        "Chamber Music",
-        "Sonata",
-        "Symphony",
-        "Booty Bass",
-        "Primus",
-        "Porn Groove",
-        "Satire",
-        "Slow Jam",
-        "Club",
-        "Tango",
-        "Samba",
-        "Folklore",
-        "Ballad",
-        "Power Ballad",
-        "Rhythmic Soul",
-        "Freestyle",
-        "Duet",
-        "Punk Rock",
-        "Drum Solo",
-        "A capella",
-        "Euro-House",
-        "Dance Hall",
-        // The following ones seem to be fairly widely supported as well
-        "Goa",
-        "Drum & Bass",
-        "Club-House",
-        "Hardcore",
-        "Terror",
-        "Indie",
-        "Britpop",
-        null,
-        "Polsk Punk",
-        "Beat",
-        "Christian Gangsta",
-        "Heavy Metal",
-        "Black Metal",
-        "Crossover",
-        "Contemporary Christian",
-        "Christian Rock",
-        "Merengue",
-        "Salsa",
-        "Thrash Metal",
-        "Anime",
-        "JPop",
-        "Synthpop",
-        // 148 and up don't seem to have been defined yet.
-    };
-
-    private long mNativeContext;
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     private final Context mContext;
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     private final String mPackageName;
-    private final String mVolumeName;
-    private final ContentProviderClient mMediaProvider;
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     private final Uri mAudioUri;
-    private final Uri mVideoUri;
-    private final Uri mImagesUri;
-    private final Uri mPlaylistsUri;
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     private final Uri mFilesUri;
-    private final Uri mFilesFullUri;
-    private final boolean mProcessPlaylists;
-    private final boolean mProcessGenres;
-    private int mMtpObjectHandle;
 
-    private final AtomicBoolean mClosed = new AtomicBoolean();
-    private final CloseGuard mCloseGuard = CloseGuard.get();
-
-    /** whether to use bulk inserts or individual inserts for each item */
-    private static final boolean ENABLE_BULK_INSERTS = true;
-
-    // used when scanning the image database so we know whether we have to prune
-    // old thumbnail files
-    private int mOriginalCount;
-    /** Whether the scanner has set a default sound for the ringer ringtone. */
-    private boolean mDefaultRingtoneSet;
-    /** Whether the scanner has set a default sound for the notification ringtone. */
-    private boolean mDefaultNotificationSet;
-    /** Whether the scanner has set a default sound for the alarm ringtone. */
-    private boolean mDefaultAlarmSet;
-    /** The filename for the default sound for the ringer ringtone. */
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     private String mDefaultRingtoneFilename;
-    /** The filename for the default sound for the notification ringtone. */
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     private String mDefaultNotificationFilename;
-    /** The filename for the default sound for the alarm ringtone. */
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     private String mDefaultAlarmAlertFilename;
-    /**
-     * The prefix for system properties that define the default sound for
-     * ringtones. Concatenate the name of the setting from Settings
-     * to get the full system property.
-     */
-    private static final String DEFAULT_RINGTONE_PROPERTY_PREFIX = "ro.config.";
-
-    private final BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
 
     private static class FileEntry {
-        @UnsupportedAppUsage
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         long mRowId;
-        String mPath;
-        long mLastModified;
-        int mFormat;
-        int mMediaType;
-        @UnsupportedAppUsage
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         boolean mLastModifiedChanged;
 
-        /** @deprecated kept intact for lame apps using reflection */
         @Deprecated
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         FileEntry(long rowId, String path, long lastModified, int format) {
-            this(rowId, path, lastModified, format, FileColumns.MEDIA_TYPE_NONE);
-        }
-
-        FileEntry(long rowId, String path, long lastModified, int format, int mediaType) {
-            mRowId = rowId;
-            mPath = path;
-            mLastModified = lastModified;
-            mFormat = format;
-            mMediaType = mediaType;
-            mLastModifiedChanged = false;
-        }
-
-        @Override
-        public String toString() {
-            return mPath + " mRowId: " + mRowId;
+            throw new UnsupportedOperationException();
         }
     }
 
-    private static class PlaylistEntry {
-        String path;
-        long bestmatchid;
-        int bestmatchlevel;
-    }
-
-    private final ArrayList<PlaylistEntry> mPlaylistEntries = new ArrayList<>();
-    private final ArrayList<FileEntry> mPlayLists = new ArrayList<>();
-
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     private MediaInserter mMediaInserter;
 
-    private DrmManagerClient mDrmManagerClient = null;
-
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     public MediaScanner(Context c, String volumeName) {
-        native_setup();
-        mContext = c;
-        mPackageName = c.getPackageName();
-        mVolumeName = volumeName;
-
-        mBitmapOptions.inSampleSize = 1;
-        mBitmapOptions.inJustDecodeBounds = true;
-
-        setDefaultRingtoneFileNames();
-
-        mMediaProvider = mContext.getContentResolver()
-                .acquireContentProviderClient(MediaStore.AUTHORITY);
-
-        if (sLastInternalScanFingerprint == null) {
-            final SharedPreferences scanSettings =
-                    mContext.getSharedPreferences(SCANNED_BUILD_PREFS_NAME, Context.MODE_PRIVATE);
-            sLastInternalScanFingerprint =
-                    scanSettings.getString(LAST_INTERNAL_SCAN_FINGERPRINT, new String());
-        }
-
-        mAudioUri = Audio.Media.getContentUri(volumeName);
-        mVideoUri = Video.Media.getContentUri(volumeName);
-        mImagesUri = Images.Media.getContentUri(volumeName);
-        mFilesUri = Files.getContentUri(volumeName);
-
-        Uri filesFullUri = mFilesUri.buildUpon().appendQueryParameter("nonotify", "1").build();
-        filesFullUri = MediaStore.setIncludePending(filesFullUri);
-        filesFullUri = MediaStore.setIncludeTrashed(filesFullUri);
-        mFilesFullUri = filesFullUri;
-
-        if (!volumeName.equals("internal")) {
-            // we only support playlists on external media
-            mProcessPlaylists = true;
-            mProcessGenres = true;
-            mPlaylistsUri = Playlists.getContentUri(volumeName);
-        } else {
-            mProcessPlaylists = false;
-            mProcessGenres = false;
-            mPlaylistsUri = null;
-        }
-
-        final Locale locale = mContext.getResources().getConfiguration().locale;
-        if (locale != null) {
-            String language = locale.getLanguage();
-            String country = locale.getCountry();
-            if (language != null) {
-                if (country != null) {
-                    setLocale(language + "_" + country);
-                } else {
-                    setLocale(language);
-                }
-            }
-        }
-
-        mCloseGuard.open("close");
+        throw new UnsupportedOperationException();
     }
 
-    private void setDefaultRingtoneFileNames() {
-        mDefaultRingtoneFilename = SystemProperties.get(DEFAULT_RINGTONE_PROPERTY_PREFIX
-                + Settings.System.RINGTONE);
-        mDefaultNotificationFilename = SystemProperties.get(DEFAULT_RINGTONE_PROPERTY_PREFIX
-                + Settings.System.NOTIFICATION_SOUND);
-        mDefaultAlarmAlertFilename = SystemProperties.get(DEFAULT_RINGTONE_PROPERTY_PREFIX
-                + Settings.System.ALARM_ALERT);
-    }
-
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     private final MyMediaScannerClient mClient = new MyMediaScannerClient();
 
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     private boolean isDrmEnabled() {
-        String prop = SystemProperties.get("drm.service.enabled");
-        return prop != null && prop.equals("true");
+        throw new UnsupportedOperationException();
     }
 
     private class MyMediaScannerClient implements MediaScannerClient {
-
-        private final SimpleDateFormat mDateFormatter;
-
-        private String mArtist;
-        private String mAlbumArtist;    // use this if mArtist is missing
-        private String mAlbum;
-        private String mTitle;
-        private String mComposer;
-        private String mGenre;
-        @UnsupportedAppUsage
-        private String mMimeType;
-        /** @deprecated file types no longer exist */
         @Deprecated
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
+        private String mMimeType;
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         private int mFileType;
-        private int mTrack;
-        private int mYear;
-        private int mDuration;
-        @UnsupportedAppUsage
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         private String mPath;
-        private long mDate;
-        private long mLastModified;
-        private long mFileSize;
-        private String mWriter;
-        private int mCompilation;
-        @UnsupportedAppUsage
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         private boolean mIsDrm;
-        @UnsupportedAppUsage
-        private boolean mNoMedia;   // flag to suppress file from appearing in media tables
-        private boolean mScanSuccess;
-        private int mWidth;
-        private int mHeight;
-        private int mColorStandard;
-        private int mColorTransfer;
-        private int mColorRange;
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
+        private boolean mNoMedia;
 
         public MyMediaScannerClient() {
-            mDateFormatter = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
-            mDateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
+            throw new UnsupportedOperationException();
         }
 
-        @UnsupportedAppUsage
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         public FileEntry beginFile(String path, String mimeType, long lastModified,
                 long fileSize, boolean isDirectory, boolean noMedia) {
-            mMimeType = mimeType;
-            mFileSize = fileSize;
-            mIsDrm = false;
-            mScanSuccess = true;
-
-            if (!isDirectory) {
-                if (!noMedia && isNoMediaFile(path)) {
-                    noMedia = true;
-                }
-                mNoMedia = noMedia;
-
-                // if mimeType was not specified, compute file type based on file extension.
-                if (mMimeType == null) {
-                    mMimeType = MediaFile.getMimeTypeForFile(path);
-                }
-
-                if (isDrmEnabled() && MediaFile.isDrmMimeType(mMimeType)) {
-                    getMimeTypeFromDrm(path);
-                }
-            }
-
-            FileEntry entry = makeEntryFor(path);
-            // add some slack to avoid a rounding error
-            long delta = (entry != null) ? (lastModified - entry.mLastModified) : 0;
-            boolean wasModified = delta > 1 || delta < -1;
-            if (entry == null || wasModified) {
-                if (wasModified) {
-                    entry.mLastModified = lastModified;
-                } else {
-                    entry = new FileEntry(0, path, lastModified,
-                            (isDirectory ? MtpConstants.FORMAT_ASSOCIATION : 0),
-                            FileColumns.MEDIA_TYPE_NONE);
-                }
-                entry.mLastModifiedChanged = true;
-            }
-
-            if (mProcessPlaylists && MediaFile.isPlayListMimeType(mMimeType)) {
-                mPlayLists.add(entry);
-                // we don't process playlists in the main scan, so return null
-                return null;
-            }
-
-            // clear all the metadata
-            mArtist = null;
-            mAlbumArtist = null;
-            mAlbum = null;
-            mTitle = null;
-            mComposer = null;
-            mGenre = null;
-            mTrack = 0;
-            mYear = 0;
-            mDuration = 0;
-            mPath = path;
-            mDate = 0;
-            mLastModified = lastModified;
-            mWriter = null;
-            mCompilation = 0;
-            mWidth = 0;
-            mHeight = 0;
-            mColorStandard = -1;
-            mColorTransfer = -1;
-            mColorRange = -1;
-
-            return entry;
+            throw new UnsupportedOperationException();
         }
 
-        @Override
-        @UnsupportedAppUsage
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         public void scanFile(String path, long lastModified, long fileSize,
                 boolean isDirectory, boolean noMedia) {
-            // This is the callback funtion from native codes.
-            // Log.v(TAG, "scanFile: "+path);
-            doScanFile(path, null, lastModified, fileSize, isDirectory, false, noMedia);
+            throw new UnsupportedOperationException();
         }
 
-        @UnsupportedAppUsage
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         public Uri doScanFile(String path, String mimeType, long lastModified,
                 long fileSize, boolean isDirectory, boolean scanAlways, boolean noMedia) {
-            Uri result = null;
-//            long t1 = System.currentTimeMillis();
-            try {
-                FileEntry entry = beginFile(path, mimeType, lastModified,
-                        fileSize, isDirectory, noMedia);
-
-                if (entry == null) {
-                    return null;
-                }
-
-                // if this file was just inserted via mtp, set the rowid to zero
-                // (even though it already exists in the database), to trigger
-                // the correct code path for updating its entry
-                if (mMtpObjectHandle != 0) {
-                    entry.mRowId = 0;
-                }
-
-                if (entry.mPath != null) {
-                    if (((!mDefaultNotificationSet &&
-                                doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename))
-                        || (!mDefaultRingtoneSet &&
-                                doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename))
-                        || (!mDefaultAlarmSet &&
-                                doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)))) {
-                        Log.w(TAG, "forcing rescan of " + entry.mPath +
-                                "since ringtone setting didn't finish");
-                        scanAlways = true;
-                    } else if (isSystemSoundWithMetadata(entry.mPath)
-                            && !Build.FINGERPRINT.equals(sLastInternalScanFingerprint)) {
-                        // file is located on the system partition where the date cannot be trusted:
-                        // rescan if the build fingerprint has changed since the last scan.
-                        Log.i(TAG, "forcing rescan of " + entry.mPath
-                                + " since build fingerprint changed");
-                        scanAlways = true;
-                    }
-                }
-
-                // rescan for metadata if file was modified since last scan
-                if (entry != null && (entry.mLastModifiedChanged || scanAlways)) {
-                    if (noMedia) {
-                        result = endFile(entry, false, false, false, false, false, false);
-                    } else {
-                        boolean isaudio = MediaFile.isAudioMimeType(mMimeType);
-                        boolean isvideo = MediaFile.isVideoMimeType(mMimeType);
-                        boolean isimage = MediaFile.isImageMimeType(mMimeType);
-
-                        if (isaudio || isvideo || isimage) {
-                            path = Environment.maybeTranslateEmulatedPathToInternal(new File(path))
-                                    .getAbsolutePath();
-                        }
-
-                        // we only extract metadata for audio and video files
-                        if (isaudio || isvideo) {
-                            mScanSuccess = processFile(path, mimeType, this);
-                        }
-
-                        if (isimage) {
-                            mScanSuccess = processImageFile(path);
-                        }
-
-                        String lowpath = path.toLowerCase(Locale.ROOT);
-                        boolean ringtones = mScanSuccess && (lowpath.indexOf(RINGTONES_DIR) > 0);
-                        boolean notifications = mScanSuccess &&
-                                (lowpath.indexOf(NOTIFICATIONS_DIR) > 0);
-                        boolean alarms = mScanSuccess && (lowpath.indexOf(ALARMS_DIR) > 0);
-                        boolean podcasts = mScanSuccess && (lowpath.indexOf(PODCASTS_DIR) > 0);
-                        boolean audiobooks = mScanSuccess && (lowpath.indexOf(AUDIOBOOKS_DIR) > 0);
-                        boolean music = mScanSuccess && ((lowpath.indexOf(MUSIC_DIR) > 0) ||
-                            (!ringtones && !notifications && !alarms && !podcasts && !audiobooks));
-
-                        result = endFile(entry, ringtones, notifications, alarms, podcasts,
-                                audiobooks, music);
-                    }
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException in MediaScanner.scanFile()", e);
-            }
-//            long t2 = System.currentTimeMillis();
-//            Log.v(TAG, "scanFile: " + path + " took " + (t2-t1));
-            return result;
+            throw new UnsupportedOperationException();
         }
 
-        private long parseDate(String date) {
-            try {
-              return mDateFormatter.parse(date).getTime();
-            } catch (ParseException e) {
-              return 0;
-            }
-        }
-
-        private int parseSubstring(String s, int start, int defaultValue) {
-            int length = s.length();
-            if (start == length) return defaultValue;
-
-            char ch = s.charAt(start++);
-            // return defaultValue if we have no integer at all
-            if (ch < '0' || ch > '9') return defaultValue;
-
-            int result = ch - '0';
-            while (start < length) {
-                ch = s.charAt(start++);
-                if (ch < '0' || ch > '9') return result;
-                result = result * 10 + (ch - '0');
-            }
-
-            return result;
-        }
-
-        @UnsupportedAppUsage
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         public void handleStringTag(String name, String value) {
-            if (name.equalsIgnoreCase("title") || name.startsWith("title;")) {
-                // Don't trim() here, to preserve the special \001 character
-                // used to force sorting. The media provider will trim() before
-                // inserting the title in to the database.
-                mTitle = value;
-            } else if (name.equalsIgnoreCase("artist") || name.startsWith("artist;")) {
-                mArtist = value.trim();
-            } else if (name.equalsIgnoreCase("albumartist") || name.startsWith("albumartist;")
-                    || name.equalsIgnoreCase("band") || name.startsWith("band;")) {
-                mAlbumArtist = value.trim();
-            } else if (name.equalsIgnoreCase("album") || name.startsWith("album;")) {
-                mAlbum = value.trim();
-            } else if (name.equalsIgnoreCase("composer") || name.startsWith("composer;")) {
-                mComposer = value.trim();
-            } else if (mProcessGenres &&
-                    (name.equalsIgnoreCase("genre") || name.startsWith("genre;"))) {
-                mGenre = getGenreName(value);
-            } else if (name.equalsIgnoreCase("year") || name.startsWith("year;")) {
-                mYear = parseSubstring(value, 0, 0);
-            } else if (name.equalsIgnoreCase("tracknumber") || name.startsWith("tracknumber;")) {
-                // track number might be of the form "2/12"
-                // we just read the number before the slash
-                int num = parseSubstring(value, 0, 0);
-                mTrack = (mTrack / 1000) * 1000 + num;
-            } else if (name.equalsIgnoreCase("discnumber") ||
-                    name.equals("set") || name.startsWith("set;")) {
-                // set number might be of the form "1/3"
-                // we just read the number before the slash
-                int num = parseSubstring(value, 0, 0);
-                mTrack = (num * 1000) + (mTrack % 1000);
-            } else if (name.equalsIgnoreCase("duration")) {
-                mDuration = parseSubstring(value, 0, 0);
-            } else if (name.equalsIgnoreCase("writer") || name.startsWith("writer;")) {
-                mWriter = value.trim();
-            } else if (name.equalsIgnoreCase("compilation")) {
-                mCompilation = parseSubstring(value, 0, 0);
-            } else if (name.equalsIgnoreCase("isdrm")) {
-                mIsDrm = (parseSubstring(value, 0, 0) == 1);
-            } else if (name.equalsIgnoreCase("date")) {
-                mDate = parseDate(value);
-            } else if (name.equalsIgnoreCase("width")) {
-                mWidth = parseSubstring(value, 0, 0);
-            } else if (name.equalsIgnoreCase("height")) {
-                mHeight = parseSubstring(value, 0, 0);
-            } else if (name.equalsIgnoreCase("colorstandard")) {
-                mColorStandard = parseSubstring(value, 0, -1);
-            } else if (name.equalsIgnoreCase("colortransfer")) {
-                mColorTransfer = parseSubstring(value, 0, -1);
-            } else if (name.equalsIgnoreCase("colorrange")) {
-                mColorRange = parseSubstring(value, 0, -1);
-            } else {
-                //Log.v(TAG, "unknown tag: " + name + " (" + mProcessGenres + ")");
-            }
+            throw new UnsupportedOperationException();
         }
 
-        private boolean convertGenreCode(String input, String expected) {
-            String output = getGenreName(input);
-            if (output.equals(expected)) {
-                return true;
-            } else {
-                Log.d(TAG, "'" + input + "' -> '" + output + "', expected '" + expected + "'");
-                return false;
-            }
-        }
-        private void testGenreNameConverter() {
-            convertGenreCode("2", "Country");
-            convertGenreCode("(2)", "Country");
-            convertGenreCode("(2", "(2");
-            convertGenreCode("2 Foo", "Country");
-            convertGenreCode("(2) Foo", "Country");
-            convertGenreCode("(2 Foo", "(2 Foo");
-            convertGenreCode("2Foo", "2Foo");
-            convertGenreCode("(2)Foo", "Country");
-            convertGenreCode("200 Foo", "Foo");
-            convertGenreCode("(200) Foo", "Foo");
-            convertGenreCode("200Foo", "200Foo");
-            convertGenreCode("(200)Foo", "Foo");
-            convertGenreCode("200)Foo", "200)Foo");
-            convertGenreCode("200) Foo", "200) Foo");
-        }
-
-        public String getGenreName(String genreTagValue) {
-
-            if (genreTagValue == null) {
-                return null;
-            }
-            final int length = genreTagValue.length();
-
-            if (length > 0) {
-                boolean parenthesized = false;
-                StringBuffer number = new StringBuffer();
-                int i = 0;
-                for (; i < length; ++i) {
-                    char c = genreTagValue.charAt(i);
-                    if (i == 0 && c == '(') {
-                        parenthesized = true;
-                    } else if (Character.isDigit(c)) {
-                        number.append(c);
-                    } else {
-                        break;
-                    }
-                }
-                char charAfterNumber = i < length ? genreTagValue.charAt(i) : ' ';
-                if ((parenthesized && charAfterNumber == ')')
-                        || !parenthesized && Character.isWhitespace(charAfterNumber)) {
-                    try {
-                        short genreIndex = Short.parseShort(number.toString());
-                        if (genreIndex >= 0) {
-                            if (genreIndex < ID3_GENRES.length && ID3_GENRES[genreIndex] != null) {
-                                return ID3_GENRES[genreIndex];
-                            } else if (genreIndex == 0xFF) {
-                                return null;
-                            } else if (genreIndex < 0xFF && (i + 1) < length) {
-                                // genre is valid but unknown,
-                                // if there is a string after the value we take it
-                                if (parenthesized && charAfterNumber == ')') {
-                                    i++;
-                                }
-                                String ret = genreTagValue.substring(i).trim();
-                                if (ret.length() != 0) {
-                                    return ret;
-                                }
-                            } else {
-                                // else return the number, without parentheses
-                                return number.toString();
-                            }
-                        }
-                    } catch (NumberFormatException e) {
-                    }
-                }
-            }
-
-            return genreTagValue;
-        }
-
-        private boolean processImageFile(String path) {
-            try {
-                mBitmapOptions.outWidth = 0;
-                mBitmapOptions.outHeight = 0;
-                BitmapFactory.decodeFile(path, mBitmapOptions);
-                mWidth = mBitmapOptions.outWidth;
-                mHeight = mBitmapOptions.outHeight;
-                return mWidth > 0 && mHeight > 0;
-            } catch (Throwable th) {
-                // ignore;
-            }
-            return false;
-        }
-
-        @UnsupportedAppUsage
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         public void setMimeType(String mimeType) {
-            if ("audio/mp4".equals(mMimeType) &&
-                    mimeType.startsWith("video")) {
-                // for feature parity with Donut, we force m4a files to keep the
-                // audio/mp4 mimetype, even if they are really "enhanced podcasts"
-                // with a video track
-                return;
-            }
-            mMimeType = mimeType;
+            throw new UnsupportedOperationException();
         }
 
-        /**
-         * Formats the data into a values array suitable for use with the Media
-         * Content Provider.
-         *
-         * @return a map of values
-         */
-        @UnsupportedAppUsage
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         private ContentValues toValues() {
-            ContentValues map = new ContentValues();
-
-            map.put(MediaStore.MediaColumns.DATA, mPath);
-            map.put(MediaStore.MediaColumns.TITLE, mTitle);
-            map.put(MediaStore.MediaColumns.DATE_MODIFIED, mLastModified);
-            map.put(MediaStore.MediaColumns.SIZE, mFileSize);
-            map.put(MediaStore.MediaColumns.MIME_TYPE, mMimeType);
-            map.put(MediaStore.MediaColumns.IS_DRM, mIsDrm);
-            map.putNull(MediaStore.MediaColumns.HASH);
-
-            String resolution = null;
-            if (mWidth > 0 && mHeight > 0) {
-                map.put(MediaStore.MediaColumns.WIDTH, mWidth);
-                map.put(MediaStore.MediaColumns.HEIGHT, mHeight);
-                resolution = mWidth + "x" + mHeight;
-            }
-
-            if (!mNoMedia) {
-                if (MediaFile.isVideoMimeType(mMimeType)) {
-                    map.put(Video.Media.ARTIST, (mArtist != null && mArtist.length() > 0
-                            ? mArtist : MediaStore.UNKNOWN_STRING));
-                    map.put(Video.Media.ALBUM, (mAlbum != null && mAlbum.length() > 0
-                            ? mAlbum : MediaStore.UNKNOWN_STRING));
-                    map.put(Video.Media.DURATION, mDuration);
-                    if (resolution != null) {
-                        map.put(Video.Media.RESOLUTION, resolution);
-                    }
-                    if (mColorStandard >= 0) {
-                        map.put(Video.Media.COLOR_STANDARD, mColorStandard);
-                    }
-                    if (mColorTransfer >= 0) {
-                        map.put(Video.Media.COLOR_TRANSFER, mColorTransfer);
-                    }
-                    if (mColorRange >= 0) {
-                        map.put(Video.Media.COLOR_RANGE, mColorRange);
-                    }
-                    if (mDate > 0) {
-                        map.put(Video.Media.DATE_TAKEN, mDate);
-                    }
-                } else if (MediaFile.isImageMimeType(mMimeType)) {
-                    // FIXME - add DESCRIPTION
-                } else if (MediaFile.isAudioMimeType(mMimeType)) {
-                    map.put(Audio.Media.ARTIST, (mArtist != null && mArtist.length() > 0) ?
-                            mArtist : MediaStore.UNKNOWN_STRING);
-                    map.put(Audio.Media.ALBUM_ARTIST, (mAlbumArtist != null &&
-                            mAlbumArtist.length() > 0) ? mAlbumArtist : null);
-                    map.put(Audio.Media.ALBUM, (mAlbum != null && mAlbum.length() > 0) ?
-                            mAlbum : MediaStore.UNKNOWN_STRING);
-                    map.put(Audio.Media.COMPOSER, mComposer);
-                    map.put(Audio.Media.GENRE, mGenre);
-                    if (mYear != 0) {
-                        map.put(Audio.Media.YEAR, mYear);
-                    }
-                    map.put(Audio.Media.TRACK, mTrack);
-                    map.put(Audio.Media.DURATION, mDuration);
-                    map.put(Audio.Media.COMPILATION, mCompilation);
-                }
-            }
-            return map;
+            throw new UnsupportedOperationException();
         }
 
-        @UnsupportedAppUsage
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         private Uri endFile(FileEntry entry, boolean ringtones, boolean notifications,
                 boolean alarms, boolean podcasts, boolean audiobooks, boolean music)
                 throws RemoteException {
-            // update database
-
-            // use album artist if artist is missing
-            if (mArtist == null || mArtist.length() == 0) {
-                mArtist = mAlbumArtist;
-            }
-
-            ContentValues values = toValues();
-            String title = values.getAsString(MediaStore.MediaColumns.TITLE);
-            if (title == null || TextUtils.isEmpty(title.trim())) {
-                title = MediaFile.getFileTitle(values.getAsString(MediaStore.MediaColumns.DATA));
-                values.put(MediaStore.MediaColumns.TITLE, title);
-            }
-            String album = values.getAsString(Audio.Media.ALBUM);
-            if (MediaStore.UNKNOWN_STRING.equals(album)) {
-                album = values.getAsString(MediaStore.MediaColumns.DATA);
-                // extract last path segment before file name
-                int lastSlash = album.lastIndexOf('/');
-                if (lastSlash >= 0) {
-                    int previousSlash = 0;
-                    while (true) {
-                        int idx = album.indexOf('/', previousSlash + 1);
-                        if (idx < 0 || idx >= lastSlash) {
-                            break;
-                        }
-                        previousSlash = idx;
-                    }
-                    if (previousSlash != 0) {
-                        album = album.substring(previousSlash + 1, lastSlash);
-                        values.put(Audio.Media.ALBUM, album);
-                    }
-                }
-            }
-            long rowId = entry.mRowId;
-            if (MediaFile.isAudioMimeType(mMimeType) && (rowId == 0 || mMtpObjectHandle != 0)) {
-                // Only set these for new entries. For existing entries, they
-                // may have been modified later, and we want to keep the current
-                // values so that custom ringtones still show up in the ringtone
-                // picker.
-                values.put(Audio.Media.IS_RINGTONE, ringtones);
-                values.put(Audio.Media.IS_NOTIFICATION, notifications);
-                values.put(Audio.Media.IS_ALARM, alarms);
-                values.put(Audio.Media.IS_MUSIC, music);
-                values.put(Audio.Media.IS_PODCAST, podcasts);
-                values.put(Audio.Media.IS_AUDIOBOOK, audiobooks);
-            } else if (MediaFile.isExifMimeType(mMimeType) && !mNoMedia) {
-                ExifInterface exif = null;
-                try {
-                    exif = new ExifInterface(entry.mPath);
-                } catch (Exception ex) {
-                    // exif is null
-                }
-                if (exif != null) {
-                    long time = exif.getGpsDateTime();
-                    if (time != -1) {
-                        values.put(Images.Media.DATE_TAKEN, time);
-                    } else {
-                        // If no time zone information is available, we should consider using
-                        // EXIF local time as taken time if the difference between file time
-                        // and EXIF local time is not less than 1 Day, otherwise MediaProvider
-                        // will use file time as taken time.
-                        time = exif.getDateTime();
-                        if (time != -1 && Math.abs(mLastModified * 1000 - time) >= 86400000) {
-                            values.put(Images.Media.DATE_TAKEN, time);
-                        }
-                    }
-
-                    int orientation = exif.getAttributeInt(
-                        ExifInterface.TAG_ORIENTATION, -1);
-                    if (orientation != -1) {
-                        // We only recognize a subset of orientation tag values.
-                        int degree;
-                        switch(orientation) {
-                            case ExifInterface.ORIENTATION_ROTATE_90:
-                                degree = 90;
-                                break;
-                            case ExifInterface.ORIENTATION_ROTATE_180:
-                                degree = 180;
-                                break;
-                            case ExifInterface.ORIENTATION_ROTATE_270:
-                                degree = 270;
-                                break;
-                            default:
-                                degree = 0;
-                                break;
-                        }
-                        values.put(Images.Media.ORIENTATION, degree);
-                    }
-                }
-            }
-
-            Uri tableUri = mFilesUri;
-            int mediaType = FileColumns.MEDIA_TYPE_NONE;
-            MediaInserter inserter = mMediaInserter;
-            if (!mNoMedia) {
-                if (MediaFile.isVideoMimeType(mMimeType)) {
-                    tableUri = mVideoUri;
-                    mediaType = FileColumns.MEDIA_TYPE_VIDEO;
-                } else if (MediaFile.isImageMimeType(mMimeType)) {
-                    tableUri = mImagesUri;
-                    mediaType = FileColumns.MEDIA_TYPE_IMAGE;
-                } else if (MediaFile.isAudioMimeType(mMimeType)) {
-                    tableUri = mAudioUri;
-                    mediaType = FileColumns.MEDIA_TYPE_AUDIO;
-                } else if (MediaFile.isPlayListMimeType(mMimeType)) {
-                    tableUri = mPlaylistsUri;
-                    mediaType = FileColumns.MEDIA_TYPE_PLAYLIST;
-                }
-            }
-            Uri result = null;
-            boolean needToSetSettings = false;
-            // Setting a flag in order not to use bulk insert for the file related with
-            // notifications, ringtones, and alarms, because the rowId of the inserted file is
-            // needed.
-            if (notifications && !mDefaultNotificationSet) {
-                if (TextUtils.isEmpty(mDefaultNotificationFilename) ||
-                        doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) {
-                    needToSetSettings = true;
-                }
-            } else if (ringtones && !mDefaultRingtoneSet) {
-                if (TextUtils.isEmpty(mDefaultRingtoneFilename) ||
-                        doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) {
-                    needToSetSettings = true;
-                }
-            } else if (alarms && !mDefaultAlarmSet) {
-                if (TextUtils.isEmpty(mDefaultAlarmAlertFilename) ||
-                        doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)) {
-                    needToSetSettings = true;
-                }
-            }
-
-            if (rowId == 0) {
-                if (mMtpObjectHandle != 0) {
-                    values.put(MediaStore.MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, mMtpObjectHandle);
-                }
-                if (tableUri == mFilesUri) {
-                    int format = entry.mFormat;
-                    if (format == 0) {
-                        format = MediaFile.getFormatCode(entry.mPath, mMimeType);
-                    }
-                    values.put(Files.FileColumns.FORMAT, format);
-                }
-                // New file, insert it.
-                // Directories need to be inserted before the files they contain, so they
-                // get priority when bulk inserting.
-                // If the rowId of the inserted file is needed, it gets inserted immediately,
-                // bypassing the bulk inserter.
-                if (inserter == null || needToSetSettings) {
-                    if (inserter != null) {
-                        inserter.flushAll();
-                    }
-                    result = mMediaProvider.insert(tableUri, values);
-                } else if (entry.mFormat == MtpConstants.FORMAT_ASSOCIATION) {
-                    inserter.insertwithPriority(tableUri, values);
-                } else {
-                    inserter.insert(tableUri, values);
-                }
-
-                if (result != null) {
-                    rowId = ContentUris.parseId(result);
-                    entry.mRowId = rowId;
-                }
-            } else {
-                // updated file
-                result = ContentUris.withAppendedId(tableUri, rowId);
-                // path should never change, and we want to avoid replacing mixed cased paths
-                // with squashed lower case paths
-                values.remove(MediaStore.MediaColumns.DATA);
-
-                if (!mNoMedia) {
-                    // Changing media type must be done as separate update
-                    if (mediaType != entry.mMediaType) {
-                        final ContentValues mediaTypeValues = new ContentValues();
-                        mediaTypeValues.put(FileColumns.MEDIA_TYPE, mediaType);
-                        mMediaProvider.update(ContentUris.withAppendedId(mFilesUri, rowId),
-                                mediaTypeValues, null, null);
-                    }
-                }
-
-                mMediaProvider.update(result, values, null, null);
-            }
-
-            if(needToSetSettings) {
-                if (notifications) {
-                    setRingtoneIfNotSet(Settings.System.NOTIFICATION_SOUND, tableUri, rowId);
-                    mDefaultNotificationSet = true;
-                } else if (ringtones) {
-                    setRingtoneIfNotSet(Settings.System.RINGTONE, tableUri, rowId);
-                    mDefaultRingtoneSet = true;
-                } else if (alarms) {
-                    setRingtoneIfNotSet(Settings.System.ALARM_ALERT, tableUri, rowId);
-                    mDefaultAlarmSet = true;
-                }
-            }
-
-            return result;
+            throw new UnsupportedOperationException();
         }
 
-        private boolean doesPathHaveFilename(String path, String filename) {
-            int pathFilenameStart = path.lastIndexOf(File.separatorChar) + 1;
-            int filenameLength = filename.length();
-            return path.regionMatches(pathFilenameStart, filename, 0, filenameLength) &&
-                    pathFilenameStart + filenameLength == path.length();
-        }
-
-        private void setRingtoneIfNotSet(String settingName, Uri uri, long rowId) {
-            if (wasRingtoneAlreadySet(settingName)) {
-                return;
-            }
-
-            ContentResolver cr = mContext.getContentResolver();
-            String existingSettingValue = Settings.System.getString(cr, settingName);
-            if (TextUtils.isEmpty(existingSettingValue)) {
-                final Uri settingUri = Settings.System.getUriFor(settingName);
-                final Uri ringtoneUri = ContentUris.withAppendedId(uri, rowId);
-                RingtoneManager.setActualDefaultRingtoneUri(mContext,
-                        RingtoneManager.getDefaultType(settingUri), ringtoneUri);
-            }
-            Settings.System.putInt(cr, settingSetIndicatorName(settingName), 1);
-        }
-
-        /** @deprecated file types no longer exist */
         @Deprecated
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
         private int getFileTypeFromDrm(String path) {
-            return 0;
-        }
-
-        private void getMimeTypeFromDrm(String path) {
-            mMimeType = null;
-
-            if (mDrmManagerClient == null) {
-                mDrmManagerClient = new DrmManagerClient(mContext);
-            }
-
-            if (mDrmManagerClient.canHandle(path, null)) {
-                mIsDrm = true;
-                mMimeType = mDrmManagerClient.getOriginalMimeType(path);
-            }
-
-            if (mMimeType == null) {
-                mMimeType = ContentResolver.MIME_TYPE_DEFAULT;
-            }
-        }
-
-    }; // end of anonymous MediaScannerClient instance
-
-    private static boolean isSystemSoundWithMetadata(String path) {
-        if (path.startsWith(SYSTEM_SOUNDS_DIR + ALARMS_DIR)
-                || path.startsWith(SYSTEM_SOUNDS_DIR + RINGTONES_DIR)
-                || path.startsWith(SYSTEM_SOUNDS_DIR + NOTIFICATIONS_DIR)
-                || path.startsWith(OEM_SOUNDS_DIR + ALARMS_DIR)
-                || path.startsWith(OEM_SOUNDS_DIR + RINGTONES_DIR)
-                || path.startsWith(OEM_SOUNDS_DIR + NOTIFICATIONS_DIR)
-                || path.startsWith(PRODUCT_SOUNDS_DIR + ALARMS_DIR)
-                || path.startsWith(PRODUCT_SOUNDS_DIR + RINGTONES_DIR)
-                || path.startsWith(PRODUCT_SOUNDS_DIR + NOTIFICATIONS_DIR)) {
-            return true;
-        }
-        return false;
-    }
-
-    private String settingSetIndicatorName(String base) {
-        return base + "_set";
-    }
-
-    private boolean wasRingtoneAlreadySet(String name) {
-        ContentResolver cr = mContext.getContentResolver();
-        String indicatorName = settingSetIndicatorName(name);
-        try {
-            return Settings.System.getInt(cr, indicatorName) != 0;
-        } catch (SettingNotFoundException e) {
-            return false;
+            throw new UnsupportedOperationException();
         }
     }
 
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     private void prescan(String filePath, boolean prescanFiles) throws RemoteException {
-        Cursor c = null;
-        String where = null;
-        String[] selectionArgs = null;
-
-        mPlayLists.clear();
-
-        if (filePath != null) {
-            // query for only one file
-            where = MediaStore.Files.FileColumns._ID + ">?" +
-                " AND " + Files.FileColumns.DATA + "=?";
-            selectionArgs = new String[] { "", filePath };
-        } else {
-            where = MediaStore.Files.FileColumns._ID + ">?";
-            selectionArgs = new String[] { "" };
-        }
-
-        mDefaultRingtoneSet = wasRingtoneAlreadySet(Settings.System.RINGTONE);
-        mDefaultNotificationSet = wasRingtoneAlreadySet(Settings.System.NOTIFICATION_SOUND);
-        mDefaultAlarmSet = wasRingtoneAlreadySet(Settings.System.ALARM_ALERT);
-
-        // Tell the provider to not delete the file.
-        // If the file is truly gone the delete is unnecessary, and we want to avoid
-        // accidentally deleting files that are really there (this may happen if the
-        // filesystem is mounted and unmounted while the scanner is running).
-        Uri.Builder builder = mFilesUri.buildUpon();
-        builder.appendQueryParameter(MediaStore.PARAM_DELETE_DATA, "false");
-        MediaBulkDeleter deleter = new MediaBulkDeleter(mMediaProvider, builder.build());
-
-        // Build the list of files from the content provider
-        try {
-            if (prescanFiles) {
-                // First read existing files from the files table.
-                // Because we'll be deleting entries for missing files as we go,
-                // we need to query the database in small batches, to avoid problems
-                // with CursorWindow positioning.
-                long lastId = Long.MIN_VALUE;
-                Uri limitUri = mFilesUri.buildUpon()
-                        .appendQueryParameter(MediaStore.PARAM_LIMIT, "1000").build();
-
-                while (true) {
-                    selectionArgs[0] = "" + lastId;
-                    if (c != null) {
-                        c.close();
-                        c = null;
-                    }
-                    c = mMediaProvider.query(limitUri, FILES_PRESCAN_PROJECTION,
-                            where, selectionArgs, MediaStore.Files.FileColumns._ID, null);
-                    if (c == null) {
-                        break;
-                    }
-
-                    int num = c.getCount();
-
-                    if (num == 0) {
-                        break;
-                    }
-                    while (c.moveToNext()) {
-                        long rowId = c.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
-                        String path = c.getString(FILES_PRESCAN_PATH_COLUMN_INDEX);
-                        int format = c.getInt(FILES_PRESCAN_FORMAT_COLUMN_INDEX);
-                        long lastModified = c.getLong(FILES_PRESCAN_DATE_MODIFIED_COLUMN_INDEX);
-                        lastId = rowId;
-
-                        // Only consider entries with absolute path names.
-                        // This allows storing URIs in the database without the
-                        // media scanner removing them.
-                        if (path != null && path.startsWith("/")) {
-                            boolean exists = false;
-                            try {
-                                exists = Os.access(path, android.system.OsConstants.F_OK);
-                            } catch (ErrnoException e1) {
-                            }
-                            if (!exists && !MtpConstants.isAbstractObject(format)) {
-                                // do not delete missing playlists, since they may have been
-                                // modified by the user.
-                                // The user can delete them in the media player instead.
-                                // instead, clear the path and lastModified fields in the row
-                                String mimeType = MediaFile.getMimeTypeForFile(path);
-                                if (!MediaFile.isPlayListMimeType(mimeType)) {
-                                    deleter.delete(rowId);
-                                    if (path.toLowerCase(Locale.US).endsWith("/.nomedia")) {
-                                        deleter.flush();
-                                        String parent = new File(path).getParent();
-                                        mMediaProvider.call(MediaStore.UNHIDE_CALL, parent, null);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        finally {
-            if (c != null) {
-                c.close();
-            }
-            deleter.flush();
-        }
-
-        // compute original size of images
-        mOriginalCount = 0;
-        c = mMediaProvider.query(mImagesUri, ID_PROJECTION, null, null, null, null);
-        if (c != null) {
-            mOriginalCount = c.getCount();
-            c.close();
-        }
+        throw new UnsupportedOperationException();
     }
 
-    static class MediaBulkDeleter {
-        StringBuilder whereClause = new StringBuilder();
-        ArrayList<String> whereArgs = new ArrayList<String>(100);
-        final ContentProviderClient mProvider;
-        final Uri mBaseUri;
-
-        public MediaBulkDeleter(ContentProviderClient provider, Uri baseUri) {
-            mProvider = provider;
-            mBaseUri = baseUri;
-        }
-
-        public void delete(long id) throws RemoteException {
-            if (whereClause.length() != 0) {
-                whereClause.append(",");
-            }
-            whereClause.append("?");
-            whereArgs.add("" + id);
-            if (whereArgs.size() > 100) {
-                flush();
-            }
-        }
-        public void flush() throws RemoteException {
-            int size = whereArgs.size();
-            if (size > 0) {
-                String [] foo = new String [size];
-                foo = whereArgs.toArray(foo);
-                int numrows = mProvider.delete(mBaseUri,
-                        MediaStore.MediaColumns._ID + " IN (" +
-                        whereClause.toString() + ")", foo);
-                //Log.i("@@@@@@@@@", "rows deleted: " + numrows);
-                whereClause.setLength(0);
-                whereArgs.clear();
-            }
-        }
-    }
-
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     private void postscan(final String[] directories) throws RemoteException {
-
-        // handle playlists last, after we know what media files are on the storage.
-        if (mProcessPlaylists) {
-            processPlayLists();
-        }
-
-        // allow GC to clean up
-        mPlayLists.clear();
+        throw new UnsupportedOperationException();
     }
 
-    private void releaseResources() {
-        // release the DrmManagerClient resources
-        if (mDrmManagerClient != null) {
-            mDrmManagerClient.close();
-            mDrmManagerClient = null;
-        }
-    }
-
-    public void scanDirectories(String[] directories) {
-        try {
-            long start = System.currentTimeMillis();
-            prescan(null, true);
-            long prescan = System.currentTimeMillis();
-
-            if (ENABLE_BULK_INSERTS) {
-                // create MediaInserter for bulk inserts
-                mMediaInserter = new MediaInserter(mMediaProvider, 500);
-            }
-
-            for (int i = 0; i < directories.length; i++) {
-                processDirectory(directories[i], mClient);
-            }
-
-            if (ENABLE_BULK_INSERTS) {
-                // flush remaining inserts
-                mMediaInserter.flushAll();
-                mMediaInserter = null;
-            }
-
-            long scan = System.currentTimeMillis();
-            postscan(directories);
-            long end = System.currentTimeMillis();
-
-            if (false) {
-                Log.d(TAG, " prescan time: " + (prescan - start) + "ms\n");
-                Log.d(TAG, "    scan time: " + (scan - prescan) + "ms\n");
-                Log.d(TAG, "postscan time: " + (end - scan) + "ms\n");
-                Log.d(TAG, "   total time: " + (end - start) + "ms\n");
-            }
-        } catch (SQLException e) {
-            // this might happen if the SD card is removed while the media scanner is running
-            Log.e(TAG, "SQLException in MediaScanner.scan()", e);
-        } catch (UnsupportedOperationException e) {
-            // this might happen if the SD card is removed while the media scanner is running
-            Log.e(TAG, "UnsupportedOperationException in MediaScanner.scan()", e);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in MediaScanner.scan()", e);
-        } finally {
-            releaseResources();
-        }
-    }
-
-    // this function is used to scan a single file
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     public Uri scanSingleFile(String path, String mimeType) {
-        try {
-            prescan(path, true);
-
-            File file = new File(path);
-            if (!file.exists() || !file.canRead()) {
-                return null;
-            }
-
-            // lastModified is in milliseconds on Files.
-            long lastModifiedSeconds = file.lastModified() / 1000;
-
-            // always scan the file, so we can return the content://media Uri for existing files
-            return mClient.doScanFile(path, mimeType, lastModifiedSeconds, file.length(),
-                    false, true, MediaScanner.isNoMediaPath(path));
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in MediaScanner.scanFile()", e);
-            return null;
-        } finally {
-            releaseResources();
-        }
+        throw new UnsupportedOperationException();
     }
 
-    private static boolean isNoMediaFile(String path) {
-        File file = new File(path);
-        if (file.isDirectory()) return false;
-
-        // special case certain file names
-        // I use regionMatches() instead of substring() below
-        // to avoid memory allocation
-        int lastSlash = path.lastIndexOf('/');
-        if (lastSlash >= 0 && lastSlash + 2 < path.length()) {
-            // ignore those ._* files created by MacOS
-            if (path.regionMatches(lastSlash + 1, "._", 0, 2)) {
-                return true;
-            }
-
-            // ignore album art files created by Windows Media Player:
-            // Folder.jpg, AlbumArtSmall.jpg, AlbumArt_{...}_Large.jpg
-            // and AlbumArt_{...}_Small.jpg
-            if (path.regionMatches(true, path.length() - 4, ".jpg", 0, 4)) {
-                if (path.regionMatches(true, lastSlash + 1, "AlbumArt_{", 0, 10) ||
-                        path.regionMatches(true, lastSlash + 1, "AlbumArt.", 0, 9)) {
-                    return true;
-                }
-                int length = path.length() - lastSlash - 1;
-                if ((length == 17 && path.regionMatches(
-                        true, lastSlash + 1, "AlbumArtSmall", 0, 13)) ||
-                        (length == 10
-                         && path.regionMatches(true, lastSlash + 1, "Folder", 0, 6))) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private static HashMap<String,String> mNoMediaPaths = new HashMap<String,String>();
-    private static HashMap<String,String> mMediaPaths = new HashMap<String,String>();
-
-    /* MediaProvider calls this when a .nomedia file is added or removed */
-    public static void clearMediaPathCache(boolean clearMediaPaths, boolean clearNoMediaPaths) {
-        synchronized (MediaScanner.class) {
-            if (clearMediaPaths) {
-                mMediaPaths.clear();
-            }
-            if (clearNoMediaPaths) {
-                mNoMediaPaths.clear();
-            }
-        }
-    }
-
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     public static boolean isNoMediaPath(String path) {
-        if (path == null) {
-            return false;
-        }
-        // return true if file or any parent directory has name starting with a dot
-        if (path.indexOf("/.") >= 0) {
-            return true;
-        }
-
-        int firstSlash = path.lastIndexOf('/');
-        if (firstSlash <= 0) {
-            return false;
-        }
-        String parent = path.substring(0,  firstSlash);
-
-        synchronized (MediaScanner.class) {
-            if (mNoMediaPaths.containsKey(parent)) {
-                return true;
-            } else if (!mMediaPaths.containsKey(parent)) {
-                // check to see if any parent directories have a ".nomedia" file
-                // start from 1 so we don't bother checking in the root directory
-                int offset = 1;
-                while (offset >= 0) {
-                    int slashIndex = path.indexOf('/', offset);
-                    if (slashIndex > offset) {
-                        slashIndex++; // move past slash
-                        File file = new File(path.substring(0, slashIndex) + ".nomedia");
-                        if (file.exists()) {
-                            // we have a .nomedia in one of the parent directories
-                            mNoMediaPaths.put(parent, "");
-                            return true;
-                        }
-                    }
-                    offset = slashIndex;
-                }
-                mMediaPaths.put(parent, "");
-            }
-        }
-
-        return isNoMediaFile(path);
+        throw new UnsupportedOperationException();
     }
 
-    public void scanMtpFile(String path, int objectHandle, int format) {
-        String mimeType = MediaFile.getMimeType(path, format);
-        File file = new File(path);
-        long lastModifiedSeconds = file.lastModified() / 1000;
-
-        if (!MediaFile.isAudioMimeType(mimeType) && !MediaFile.isVideoMimeType(mimeType) &&
-            !MediaFile.isImageMimeType(mimeType) && !MediaFile.isPlayListMimeType(mimeType) &&
-            !MediaFile.isDrmMimeType(mimeType)) {
-
-            // no need to use the media scanner, but we need to update last modified and file size
-            ContentValues values = new ContentValues();
-            values.put(Files.FileColumns.SIZE, file.length());
-            values.put(Files.FileColumns.DATE_MODIFIED, lastModifiedSeconds);
-            try {
-                String[] whereArgs = new String[] {  Integer.toString(objectHandle) };
-                mMediaProvider.update(Files.getMtpObjectsUri(mVolumeName), values,
-                        "_id=?", whereArgs);
-            } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException in scanMtpFile", e);
-            }
-            return;
-        }
-
-        mMtpObjectHandle = objectHandle;
-        Cursor fileList = null;
-        try {
-            if (MediaFile.isPlayListMimeType(mimeType)) {
-                // build file cache so we can look up tracks in the playlist
-                prescan(null, true);
-
-                FileEntry entry = makeEntryFor(path);
-                if (entry != null) {
-                    fileList = mMediaProvider.query(mFilesUri,
-                            FILES_PRESCAN_PROJECTION, null, null, null, null);
-                    processPlayList(entry, fileList);
-                }
-            } else {
-                // MTP will create a file entry for us so we don't want to do it in prescan
-                prescan(path, false);
-
-                // always scan the file, so we can return the content://media Uri for existing files
-                mClient.doScanFile(path, mimeType, lastModifiedSeconds, file.length(),
-                    (format == MtpConstants.FORMAT_ASSOCIATION), true, isNoMediaPath(path));
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in MediaScanner.scanFile()", e);
-        } finally {
-            mMtpObjectHandle = 0;
-            if (fileList != null) {
-                fileList.close();
-            }
-            releaseResources();
-        }
-    }
-
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
     FileEntry makeEntryFor(String path) {
-        String where;
-        String[] selectionArgs;
-
-        Cursor c = null;
-        try {
-            where = Files.FileColumns.DATA + "=?";
-            selectionArgs = new String[] { path };
-            c = mMediaProvider.query(mFilesFullUri, FILES_PRESCAN_PROJECTION,
-                    where, selectionArgs, null, null);
-            if (c != null && c.moveToFirst()) {
-                long rowId = c.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
-                long lastModified = c.getLong(FILES_PRESCAN_DATE_MODIFIED_COLUMN_INDEX);
-                int format = c.getInt(FILES_PRESCAN_FORMAT_COLUMN_INDEX);
-                int mediaType = c.getInt(FILES_PRESCAN_MEDIA_TYPE_COLUMN_INDEX);
-                return new FileEntry(rowId, path, lastModified, format, mediaType);
-            }
-        } catch (RemoteException e) {
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-        return null;
+        throw new UnsupportedOperationException();
     }
 
-    // returns the number of matching file/directory names, starting from the right
-    private int matchPaths(String path1, String path2) {
-        int result = 0;
-        int end1 = path1.length();
-        int end2 = path2.length();
-
-        while (end1 > 0 && end2 > 0) {
-            int slash1 = path1.lastIndexOf('/', end1 - 1);
-            int slash2 = path2.lastIndexOf('/', end2 - 1);
-            int backSlash1 = path1.lastIndexOf('\\', end1 - 1);
-            int backSlash2 = path2.lastIndexOf('\\', end2 - 1);
-            int start1 = (slash1 > backSlash1 ? slash1 : backSlash1);
-            int start2 = (slash2 > backSlash2 ? slash2 : backSlash2);
-            if (start1 < 0) start1 = 0; else start1++;
-            if (start2 < 0) start2 = 0; else start2++;
-            int length = end1 - start1;
-            if (end2 - start2 != length) break;
-            if (path1.regionMatches(true, start1, path2, start2, length)) {
-                result++;
-                end1 = start1 - 1;
-                end2 = start2 - 1;
-            } else break;
-        }
-
-        return result;
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "All scanning requests should be performed through {@link android.media.MediaScannerConnection}")
+    private void setLocale(String locale) {
+        throw new UnsupportedOperationException();
     }
 
-    private boolean matchEntries(long rowId, String data) {
-
-        int len = mPlaylistEntries.size();
-        boolean done = true;
-        for (int i = 0; i < len; i++) {
-            PlaylistEntry entry = mPlaylistEntries.get(i);
-            if (entry.bestmatchlevel == Integer.MAX_VALUE) {
-                continue; // this entry has been matched already
-            }
-            done = false;
-            if (data.equalsIgnoreCase(entry.path)) {
-                entry.bestmatchid = rowId;
-                entry.bestmatchlevel = Integer.MAX_VALUE;
-                continue; // no need for path matching
-            }
-
-            int matchLength = matchPaths(data, entry.path);
-            if (matchLength > entry.bestmatchlevel) {
-                entry.bestmatchid = rowId;
-                entry.bestmatchlevel = matchLength;
-            }
-        }
-        return done;
-    }
-
-    private void cachePlaylistEntry(String line, String playListDirectory) {
-        PlaylistEntry entry = new PlaylistEntry();
-        // watch for trailing whitespace
-        int entryLength = line.length();
-        while (entryLength > 0 && Character.isWhitespace(line.charAt(entryLength - 1))) entryLength--;
-        // path should be longer than 3 characters.
-        // avoid index out of bounds errors below by returning here.
-        if (entryLength < 3) return;
-        if (entryLength < line.length()) line = line.substring(0, entryLength);
-
-        // does entry appear to be an absolute path?
-        // look for Unix or DOS absolute paths
-        char ch1 = line.charAt(0);
-        boolean fullPath = (ch1 == '/' ||
-                (Character.isLetter(ch1) && line.charAt(1) == ':' && line.charAt(2) == '\\'));
-        // if we have a relative path, combine entry with playListDirectory
-        if (!fullPath)
-            line = playListDirectory + line;
-        entry.path = line;
-        //FIXME - should we look for "../" within the path?
-
-        mPlaylistEntries.add(entry);
-    }
-
-    private void processCachedPlaylist(Cursor fileList, ContentValues values, Uri playlistUri) {
-        fileList.moveToPosition(-1);
-        while (fileList.moveToNext()) {
-            long rowId = fileList.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
-            String data = fileList.getString(FILES_PRESCAN_PATH_COLUMN_INDEX);
-            if (matchEntries(rowId, data)) {
-                break;
-            }
-        }
-
-        int len = mPlaylistEntries.size();
-        int index = 0;
-        for (int i = 0; i < len; i++) {
-            PlaylistEntry entry = mPlaylistEntries.get(i);
-            if (entry.bestmatchlevel > 0) {
-                try {
-                    values.clear();
-                    values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(index));
-                    values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, Long.valueOf(entry.bestmatchid));
-                    mMediaProvider.insert(playlistUri, values);
-                    index++;
-                } catch (RemoteException e) {
-                    Log.e(TAG, "RemoteException in MediaScanner.processCachedPlaylist()", e);
-                    return;
-                }
-            }
-        }
-        mPlaylistEntries.clear();
-    }
-
-    private void processM3uPlayList(String path, String playListDirectory, Uri uri,
-            ContentValues values, Cursor fileList) {
-        BufferedReader reader = null;
-        try {
-            File f = new File(path);
-            if (f.exists()) {
-                reader = new BufferedReader(
-                        new InputStreamReader(new FileInputStream(f)), 8192);
-                String line = reader.readLine();
-                mPlaylistEntries.clear();
-                while (line != null) {
-                    // ignore comment lines, which begin with '#'
-                    if (line.length() > 0 && line.charAt(0) != '#') {
-                        cachePlaylistEntry(line, playListDirectory);
-                    }
-                    line = reader.readLine();
-                }
-
-                processCachedPlaylist(fileList, values, uri);
-            }
-        } catch (IOException e) {
-            Log.e(TAG, "IOException in MediaScanner.processM3uPlayList()", e);
-        } finally {
-            try {
-                if (reader != null)
-                    reader.close();
-            } catch (IOException e) {
-                Log.e(TAG, "IOException in MediaScanner.processM3uPlayList()", e);
-            }
-        }
-    }
-
-    private void processPlsPlayList(String path, String playListDirectory, Uri uri,
-            ContentValues values, Cursor fileList) {
-        BufferedReader reader = null;
-        try {
-            File f = new File(path);
-            if (f.exists()) {
-                reader = new BufferedReader(
-                        new InputStreamReader(new FileInputStream(f)), 8192);
-                String line = reader.readLine();
-                mPlaylistEntries.clear();
-                while (line != null) {
-                    // ignore comment lines, which begin with '#'
-                    if (line.startsWith("File")) {
-                        int equals = line.indexOf('=');
-                        if (equals > 0) {
-                            cachePlaylistEntry(line.substring(equals + 1), playListDirectory);
-                        }
-                    }
-                    line = reader.readLine();
-                }
-
-                processCachedPlaylist(fileList, values, uri);
-            }
-        } catch (IOException e) {
-            Log.e(TAG, "IOException in MediaScanner.processPlsPlayList()", e);
-        } finally {
-            try {
-                if (reader != null)
-                    reader.close();
-            } catch (IOException e) {
-                Log.e(TAG, "IOException in MediaScanner.processPlsPlayList()", e);
-            }
-        }
-    }
-
-    class WplHandler implements ElementListener {
-
-        final ContentHandler handler;
-        String playListDirectory;
-
-        public WplHandler(String playListDirectory, Uri uri, Cursor fileList) {
-            this.playListDirectory = playListDirectory;
-
-            RootElement root = new RootElement("smil");
-            Element body = root.getChild("body");
-            Element seq = body.getChild("seq");
-            Element media = seq.getChild("media");
-            media.setElementListener(this);
-
-            this.handler = root.getContentHandler();
-        }
-
-        @Override
-        public void start(Attributes attributes) {
-            String path = attributes.getValue("", "src");
-            if (path != null) {
-                cachePlaylistEntry(path, playListDirectory);
-            }
-        }
-
-       @Override
-       public void end() {
-       }
-
-        ContentHandler getContentHandler() {
-            return handler;
-        }
-    }
-
-    private void processWplPlayList(String path, String playListDirectory, Uri uri,
-            ContentValues values, Cursor fileList) {
-        FileInputStream fis = null;
-        try {
-            File f = new File(path);
-            if (f.exists()) {
-                fis = new FileInputStream(f);
-
-                mPlaylistEntries.clear();
-                Xml.parse(fis, Xml.findEncodingByName("UTF-8"),
-                        new WplHandler(playListDirectory, uri, fileList).getContentHandler());
-
-                processCachedPlaylist(fileList, values, uri);
-            }
-        } catch (SAXException e) {
-            e.printStackTrace();
-        } catch (IOException e) {
-            e.printStackTrace();
-        } finally {
-            try {
-                if (fis != null)
-                    fis.close();
-            } catch (IOException e) {
-                Log.e(TAG, "IOException in MediaScanner.processWplPlayList()", e);
-            }
-        }
-    }
-
-    private void processPlayList(FileEntry entry, Cursor fileList) throws RemoteException {
-        String path = entry.mPath;
-        ContentValues values = new ContentValues();
-        int lastSlash = path.lastIndexOf('/');
-        if (lastSlash < 0) throw new IllegalArgumentException("bad path " + path);
-        Uri uri, membersUri;
-        long rowId = entry.mRowId;
-
-        // make sure we have a name
-        String name = values.getAsString(MediaStore.Audio.Playlists.NAME);
-        if (name == null) {
-            name = values.getAsString(MediaStore.MediaColumns.TITLE);
-            if (name == null) {
-                // extract name from file name
-                int lastDot = path.lastIndexOf('.');
-                name = (lastDot < 0 ? path.substring(lastSlash + 1)
-                        : path.substring(lastSlash + 1, lastDot));
-            }
-        }
-
-        values.put(MediaStore.Audio.Playlists.NAME, name);
-        values.put(MediaStore.Audio.Playlists.DATE_MODIFIED, entry.mLastModified);
-
-        if (rowId == 0) {
-            values.put(MediaStore.Audio.Playlists.DATA, path);
-            uri = mMediaProvider.insert(mPlaylistsUri, values);
-            rowId = ContentUris.parseId(uri);
-            membersUri = Uri.withAppendedPath(uri, Playlists.Members.CONTENT_DIRECTORY);
-        } else {
-            uri = ContentUris.withAppendedId(mPlaylistsUri, rowId);
-            mMediaProvider.update(uri, values, null, null);
-
-            // delete members of existing playlist
-            membersUri = Uri.withAppendedPath(uri, Playlists.Members.CONTENT_DIRECTORY);
-            mMediaProvider.delete(membersUri, null, null);
-        }
-
-        String playListDirectory = path.substring(0, lastSlash + 1);
-        String mimeType = MediaFile.getMimeTypeForFile(path);
-        switch (mimeType) {
-            case "application/vnd.ms-wpl":
-                processWplPlayList(path, playListDirectory, membersUri, values, fileList);
-                break;
-            case "audio/x-mpegurl":
-                processM3uPlayList(path, playListDirectory, membersUri, values, fileList);
-                break;
-            case "audio/x-scpls":
-                processPlsPlayList(path, playListDirectory, membersUri, values, fileList);
-                break;
-        }
-    }
-
-    private void processPlayLists() throws RemoteException {
-        Iterator<FileEntry> iterator = mPlayLists.iterator();
-        Cursor fileList = null;
-        try {
-            // use the files uri and projection because we need the format column,
-            // but restrict the query to just audio files
-            fileList = mMediaProvider.query(mFilesUri, FILES_PRESCAN_PROJECTION,
-                    "media_type=2", null, null, null);
-            while (iterator.hasNext()) {
-                FileEntry entry = iterator.next();
-                // only process playlist files if they are new or have been modified since the last scan
-                if (entry.mLastModifiedChanged) {
-                    processPlayList(entry, fileList);
-                }
-            }
-        } catch (RemoteException e1) {
-        } finally {
-            if (fileList != null) {
-                fileList.close();
-            }
-        }
-    }
-
-    private native void processDirectory(String path, MediaScannerClient client);
-    private native boolean processFile(String path, String mimeType, MediaScannerClient client);
-    @UnsupportedAppUsage
-    private native void setLocale(String locale);
-
-    public native byte[] extractAlbumArt(FileDescriptor fd);
-
-    private static native final void native_init();
-    private native final void native_setup();
-    private native final void native_finalize();
-
     @Override
     public void close() {
-        mCloseGuard.close();
-        if (mClosed.compareAndSet(false, true)) {
-            mMediaProvider.close();
-            native_finalize();
-        }
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            if (mCloseGuard != null) {
-                mCloseGuard.warnIfOpen();
-            }
-
-            close();
-        } finally {
-            super.finalize();
-        }
+        throw new UnsupportedOperationException();
     }
 }
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 435d8d7..ff40442 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -846,7 +846,7 @@
      * Adds an audio file to the list of ringtones.
      *
      * After making sure the given file is an audio file, copies the file to the ringtone storage,
-     * and asks the {@link android.media.MediaScanner} to scan that file. This call will block until
+     * and asks the system to scan that file. This call will block until
      * the scan is completed.
      *
      * The directory where the copied file is stored is the directory that matches the ringtone's
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 45ee210..b4edabf 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -4,6 +4,7 @@
     srcs: [
         "android_media_ImageWriter.cpp",
         "android_media_ImageReader.cpp",
+        "android_media_JetPlayer.cpp",
         "android_media_MediaCrypto.cpp",
         "android_media_MediaCodec.cpp",
         "android_media_MediaCodecList.cpp",
@@ -17,7 +18,6 @@
         "android_media_MediaPlayer.cpp",
         "android_media_MediaProfiles.cpp",
         "android_media_MediaRecorder.cpp",
-        "android_media_MediaScanner.cpp",
         "android_media_MediaSync.cpp",
         "android_media_ResampleInputStream.cpp",
         "android_media_Streams.cpp",
@@ -25,10 +25,12 @@
         "android_mtp_MtpDatabase.cpp",
         "android_mtp_MtpDevice.cpp",
         "android_mtp_MtpServer.cpp",
+        "JetPlayer.cpp",
     ],
 
     shared_libs: [
         "libandroid_runtime",
+        "libaudioclient",
         "libnativehelper",
         "libnativewindow",
         "libutils",
@@ -53,6 +55,7 @@
         "libandroidfw",
         "libhidlallocatorutils",
         "libhidlbase",
+        "libsonivox",
         "android.hardware.cas@1.0",
         "android.hardware.cas.native@1.0",
         "android.hidl.memory@1.0",
@@ -64,7 +67,10 @@
         "libmediadrm_headers",
     ],
 
-    static_libs: ["libgrallocusage"],
+    static_libs: [
+        "libgrallocusage",
+        "libmedia_midiiowrapper",
+    ],
 
     include_dirs: [
         "frameworks/base/core/jni",
diff --git a/media/jni/JetPlayer.cpp b/media/jni/JetPlayer.cpp
new file mode 100644
index 0000000..358feb7
--- /dev/null
+++ b/media/jni/JetPlayer.cpp
@@ -0,0 +1,471 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "JetPlayer-C"
+
+#include <utils/Log.h>
+#include "JetPlayer.h"
+
+
+namespace android
+{
+
+static const int MIX_NUM_BUFFERS = 4;
+static const S_EAS_LIB_CONFIG* pLibConfig = NULL;
+
+//-------------------------------------------------------------------------------------------------
+JetPlayer::JetPlayer(void *javaJetPlayer, int maxTracks, int trackBufferSize) :
+        mEventCallback(NULL),
+        mJavaJetPlayerRef(javaJetPlayer),
+        mTid(-1),
+        mRender(false),
+        mPaused(false),
+        mMaxTracks(maxTracks),
+        mEasData(NULL),
+        mIoWrapper(NULL),
+        mTrackBufferSize(trackBufferSize)
+{
+    ALOGV("JetPlayer constructor");
+    mPreviousJetStatus.currentUserID = -1;
+    mPreviousJetStatus.segmentRepeatCount = -1;
+    mPreviousJetStatus.numQueuedSegments = -1;
+    mPreviousJetStatus.paused = true;
+}
+
+//-------------------------------------------------------------------------------------------------
+JetPlayer::~JetPlayer()
+{
+    ALOGV("~JetPlayer");
+    release();
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::init()
+{
+    //Mutex::Autolock lock(&mMutex);
+
+    EAS_RESULT result;
+
+    // retrieve the EAS library settings
+    if (pLibConfig == NULL)
+        pLibConfig = EAS_Config();
+    if (pLibConfig == NULL) {
+        ALOGE("JetPlayer::init(): EAS library configuration could not be retrieved, aborting.");
+        return EAS_FAILURE;
+    }
+
+    // init the EAS library
+    result = EAS_Init(&mEasData);
+    if (result != EAS_SUCCESS) {
+        ALOGE("JetPlayer::init(): Error initializing Sonivox EAS library, aborting.");
+        mState = EAS_STATE_ERROR;
+        return result;
+    }
+    // init the JET library with the default app event controller range
+    result = JET_Init(mEasData, NULL, sizeof(S_JET_CONFIG));
+    if (result != EAS_SUCCESS) {
+        ALOGE("JetPlayer::init(): Error initializing JET library, aborting.");
+        mState = EAS_STATE_ERROR;
+        return result;
+    }
+
+    // create the output AudioTrack
+    mAudioTrack = new AudioTrack();
+    status_t status = mAudioTrack->set(AUDIO_STREAM_MUSIC,  //TODO parameterize this
+            pLibConfig->sampleRate,
+            AUDIO_FORMAT_PCM_16_BIT,
+            audio_channel_out_mask_from_count(pLibConfig->numChannels),
+            (size_t) mTrackBufferSize,
+            AUDIO_OUTPUT_FLAG_NONE);
+    if (status != OK) {
+        ALOGE("JetPlayer::init(): Error initializing JET library; AudioTrack error %d", status);
+        mAudioTrack.clear();
+        mState = EAS_STATE_ERROR;
+        return EAS_FAILURE;
+    }
+
+    // create render and playback thread
+    {
+        Mutex::Autolock l(mMutex);
+        ALOGV("JetPlayer::init(): trying to start render thread");
+        mThread = new JetPlayerThread(this);
+        mThread->run("jetRenderThread", ANDROID_PRIORITY_AUDIO);
+        mCondition.wait(mMutex);
+    }
+    if (mTid > 0) {
+        // render thread started, we're ready
+        ALOGV("JetPlayer::init(): render thread(%d) successfully started.", mTid);
+        mState = EAS_STATE_READY;
+    } else {
+        ALOGE("JetPlayer::init(): failed to start render thread.");
+        mState = EAS_STATE_ERROR;
+        return EAS_FAILURE;
+    }
+
+    return EAS_SUCCESS;
+}
+
+void JetPlayer::setEventCallback(jetevent_callback eventCallback)
+{
+    Mutex::Autolock l(mMutex);
+    mEventCallback = eventCallback;
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::release()
+{
+    ALOGV("JetPlayer::release()");
+    Mutex::Autolock lock(mMutex);
+    mPaused = true;
+    mRender = false;
+    if (mEasData) {
+        JET_Pause(mEasData);
+        JET_CloseFile(mEasData);
+        JET_Shutdown(mEasData);
+        EAS_Shutdown(mEasData);
+    }
+    delete mIoWrapper;
+    mIoWrapper = NULL;
+    if (mAudioTrack != 0) {
+        mAudioTrack->stop();
+        mAudioTrack->flush();
+        mAudioTrack.clear();
+    }
+    if (mAudioBuffer) {
+        delete mAudioBuffer;
+        mAudioBuffer = NULL;
+    }
+    mEasData = NULL;
+
+    return EAS_SUCCESS;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::render() {
+    EAS_RESULT result = EAS_FAILURE;
+    EAS_I32 count;
+    int temp;
+    bool audioStarted = false;
+
+    ALOGV("JetPlayer::render(): entering");
+
+    // allocate render buffer
+    mAudioBuffer =
+        new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * MIX_NUM_BUFFERS];
+
+    // signal main thread that we started
+    {
+        Mutex::Autolock l(mMutex);
+        mTid = gettid();
+        ALOGV("JetPlayer::render(): render thread(%d) signal", mTid);
+        mCondition.signal();
+    }
+
+    while (1) {
+
+        mMutex.lock(); // [[[[[[[[ LOCK ---------------------------------------
+
+        if (mEasData == NULL) {
+            mMutex.unlock();
+            ALOGV("JetPlayer::render(): NULL EAS data, exiting render.");
+            goto threadExit;
+        }
+
+        // nothing to render, wait for client thread to wake us up
+        while (!mRender)
+        {
+            ALOGV("JetPlayer::render(): signal wait");
+            if (audioStarted) {
+                mAudioTrack->pause();
+                // we have to restart the playback once we start rendering again
+                audioStarted = false;
+            }
+            mCondition.wait(mMutex);
+            ALOGV("JetPlayer::render(): signal rx'd");
+        }
+
+        // render midi data into the input buffer
+        int num_output = 0;
+        EAS_PCM* p = mAudioBuffer;
+        for (int i = 0; i < MIX_NUM_BUFFERS; i++) {
+            result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
+            if (result != EAS_SUCCESS) {
+                ALOGE("JetPlayer::render(): EAS_Render returned error %ld", result);
+            }
+            p += count * pLibConfig->numChannels;
+            num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
+
+            // send events that were generated (if any) to the event callback
+            fireEventsFromJetQueue();
+        }
+
+        // update playback state
+        //ALOGV("JetPlayer::render(): updating state");
+        JET_Status(mEasData, &mJetStatus);
+        fireUpdateOnStatusChange();
+        mPaused = mJetStatus.paused;
+
+        mMutex.unlock(); // UNLOCK ]]]]]]]] -----------------------------------
+
+        // check audio output track
+        if (mAudioTrack == NULL) {
+            ALOGE("JetPlayer::render(): output AudioTrack was not created");
+            goto threadExit;
+        }
+
+        // Write data to the audio hardware
+        //ALOGV("JetPlayer::render(): writing to audio output");
+        if ((temp = mAudioTrack->write(mAudioBuffer, num_output)) < 0) {
+            ALOGE("JetPlayer::render(): Error in writing:%d",temp);
+            return temp;
+        }
+
+        // start audio output if necessary
+        if (!audioStarted) {
+            ALOGV("JetPlayer::render(): starting audio playback");
+            mAudioTrack->start();
+            audioStarted = true;
+        }
+
+    }//while (1)
+
+threadExit:
+    if (mAudioTrack != NULL) {
+        mAudioTrack->stop();
+        mAudioTrack->flush();
+    }
+    delete [] mAudioBuffer;
+    mAudioBuffer = NULL;
+    mMutex.lock();
+    mTid = -1;
+    mCondition.signal();
+    mMutex.unlock();
+    return result;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+// fire up an update if any of the status fields has changed
+// precondition: mMutex locked
+void JetPlayer::fireUpdateOnStatusChange()
+{
+    if ( (mJetStatus.currentUserID      != mPreviousJetStatus.currentUserID)
+       ||(mJetStatus.segmentRepeatCount != mPreviousJetStatus.segmentRepeatCount) ) {
+        if (mEventCallback)  {
+            mEventCallback(
+                JetPlayer::JET_USERID_UPDATE,
+                mJetStatus.currentUserID,
+                mJetStatus.segmentRepeatCount,
+                mJavaJetPlayerRef);
+        }
+        mPreviousJetStatus.currentUserID      = mJetStatus.currentUserID;
+        mPreviousJetStatus.segmentRepeatCount = mJetStatus.segmentRepeatCount;
+    }
+
+    if (mJetStatus.numQueuedSegments != mPreviousJetStatus.numQueuedSegments) {
+        if (mEventCallback)  {
+            mEventCallback(
+                JetPlayer::JET_NUMQUEUEDSEGMENT_UPDATE,
+                mJetStatus.numQueuedSegments,
+                -1,
+                mJavaJetPlayerRef);
+        }
+        mPreviousJetStatus.numQueuedSegments  = mJetStatus.numQueuedSegments;
+    }
+
+    if (mJetStatus.paused != mPreviousJetStatus.paused) {
+        if (mEventCallback)  {
+            mEventCallback(JetPlayer::JET_PAUSE_UPDATE,
+                mJetStatus.paused,
+                -1,
+                mJavaJetPlayerRef);
+        }
+        mPreviousJetStatus.paused = mJetStatus.paused;
+    }
+
+}
+
+
+//-------------------------------------------------------------------------------------------------
+// fire up all the JET events in the JET engine queue (until the queue is empty)
+// precondition: mMutex locked
+void JetPlayer::fireEventsFromJetQueue()
+{
+    if (!mEventCallback) {
+        // no callback, just empty the event queue
+        while (JET_GetEvent(mEasData, NULL, NULL)) { }
+        return;
+    }
+
+    EAS_U32 rawEvent;
+    while (JET_GetEvent(mEasData, &rawEvent, NULL)) {
+        mEventCallback(
+            JetPlayer::JET_EVENT,
+            rawEvent,
+            -1,
+            mJavaJetPlayerRef);
+    }
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::loadFromFile(const char* path)
+{
+    ALOGV("JetPlayer::loadFromFile(): path=%s", path);
+
+    Mutex::Autolock lock(mMutex);
+
+    delete mIoWrapper;
+    mIoWrapper = new MidiIoWrapper(path);
+
+    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
+    if (result != EAS_SUCCESS)
+        mState = EAS_STATE_ERROR;
+    else
+        mState = EAS_STATE_OPEN;
+    return( result );
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::loadFromFD(const int fd, const long long offset, const long long length)
+{
+    ALOGV("JetPlayer::loadFromFD(): fd=%d offset=%lld length=%lld", fd, offset, length);
+
+    Mutex::Autolock lock(mMutex);
+
+    delete mIoWrapper;
+    mIoWrapper = new MidiIoWrapper(fd, offset, length);
+
+    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
+    if (result != EAS_SUCCESS)
+        mState = EAS_STATE_ERROR;
+    else
+        mState = EAS_STATE_OPEN;
+    return( result );
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::closeFile()
+{
+    Mutex::Autolock lock(mMutex);
+    return JET_CloseFile(mEasData);
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::play()
+{
+    ALOGV("JetPlayer::play(): entering");
+    Mutex::Autolock lock(mMutex);
+
+    EAS_RESULT result = JET_Play(mEasData);
+
+    mPaused = false;
+    mRender = true;
+
+    JET_Status(mEasData, &mJetStatus);
+    this->dumpJetStatus(&mJetStatus);
+
+    fireUpdateOnStatusChange();
+
+    // wake up render thread
+    ALOGV("JetPlayer::play(): wakeup render thread");
+    mCondition.signal();
+
+    return result;
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::pause()
+{
+    Mutex::Autolock lock(mMutex);
+    mPaused = true;
+    EAS_RESULT result = JET_Pause(mEasData);
+
+    mRender = false;
+
+    JET_Status(mEasData, &mJetStatus);
+    this->dumpJetStatus(&mJetStatus);
+    fireUpdateOnStatusChange();
+
+
+    return result;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::queueSegment(int segmentNum, int libNum, int repeatCount, int transpose,
+        EAS_U32 muteFlags, EAS_U8 userID)
+{
+    ALOGV("JetPlayer::queueSegment segmentNum=%d, libNum=%d, repeatCount=%d, transpose=%d",
+        segmentNum, libNum, repeatCount, transpose);
+    Mutex::Autolock lock(mMutex);
+    return JET_QueueSegment(mEasData, segmentNum, libNum, repeatCount, transpose, muteFlags,
+            userID);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::setMuteFlags(EAS_U32 muteFlags, bool sync)
+{
+    Mutex::Autolock lock(mMutex);
+    return JET_SetMuteFlags(mEasData, muteFlags, sync);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::setMuteFlag(int trackNum, bool muteFlag, bool sync)
+{
+    Mutex::Autolock lock(mMutex);
+    return JET_SetMuteFlag(mEasData, trackNum, muteFlag, sync);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::triggerClip(int clipId)
+{
+    ALOGV("JetPlayer::triggerClip clipId=%d", clipId);
+    Mutex::Autolock lock(mMutex);
+    return JET_TriggerClip(mEasData, clipId);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::clearQueue()
+{
+    ALOGV("JetPlayer::clearQueue");
+    Mutex::Autolock lock(mMutex);
+    return JET_Clear_Queue(mEasData);
+}
+
+//-------------------------------------------------------------------------------------------------
+void JetPlayer::dump()
+{
+}
+
+void JetPlayer::dumpJetStatus(S_JET_STATUS* pJetStatus)
+{
+    if (pJetStatus!=NULL)
+        ALOGV(">> current JET player status: userID=%d segmentRepeatCount=%d numQueuedSegments=%d "
+                "paused=%d",
+                pJetStatus->currentUserID, pJetStatus->segmentRepeatCount,
+                pJetStatus->numQueuedSegments, pJetStatus->paused);
+    else
+        ALOGE(">> JET player status is NULL");
+}
+
+
+} // end namespace android
diff --git a/media/jni/JetPlayer.h b/media/jni/JetPlayer.h
new file mode 100644
index 0000000..bb569bc
--- /dev/null
+++ b/media/jni/JetPlayer.h
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+#ifndef JETPLAYER_H_
+#define JETPLAYER_H_
+
+#include <utils/threads.h>
+
+#include <libsonivox/jet.h>
+#include <libsonivox/eas_types.h>
+#include <media/AudioTrack.h>
+#include <media/MidiIoWrapper.h>
+
+
+namespace android {
+
+typedef void (*jetevent_callback)(int eventType, int val1, int val2, void *cookie);
+
+class JetPlayer {
+
+public:
+
+    // to keep in sync with the JetPlayer class constants
+    // defined in frameworks/base/media/java/android/media/JetPlayer.java
+    static const int JET_EVENT                   = 1;
+    static const int JET_USERID_UPDATE           = 2;
+    static const int JET_NUMQUEUEDSEGMENT_UPDATE = 3;
+    static const int JET_PAUSE_UPDATE            = 4;
+
+    JetPlayer(void *javaJetPlayer,
+            int maxTracks = 32,
+            int trackBufferSize = 1200);
+    ~JetPlayer();
+    int init();
+    int release();
+
+    int loadFromFile(const char* url);
+    int loadFromFD(const int fd, const long long offset, const long long length);
+    int closeFile();
+    int play();
+    int pause();
+    int queueSegment(int segmentNum, int libNum, int repeatCount, int transpose,
+            EAS_U32 muteFlags, EAS_U8 userID);
+    int setMuteFlags(EAS_U32 muteFlags, bool sync);
+    int setMuteFlag(int trackNum, bool muteFlag, bool sync);
+    int triggerClip(int clipId);
+    int clearQueue();
+
+    void setEventCallback(jetevent_callback callback);
+
+    int getMaxTracks() { return mMaxTracks; };
+
+
+private:
+    int                 render();
+    void                fireUpdateOnStatusChange();
+    void                fireEventsFromJetQueue();
+
+    JetPlayer() {} // no default constructor
+    void dump();
+    void dumpJetStatus(S_JET_STATUS* pJetStatus);
+
+    jetevent_callback   mEventCallback;
+
+    void*               mJavaJetPlayerRef;
+    Mutex               mMutex; // mutex to sync the render and playback thread with the JET calls
+    pid_t               mTid;
+    Condition           mCondition;
+    volatile bool       mRender;
+    bool                mPaused;
+
+    EAS_STATE           mState;
+    int*                mMemFailedVar;
+
+    int                 mMaxTracks; // max number of MIDI tracks, usually 32
+    EAS_DATA_HANDLE     mEasData;
+    MidiIoWrapper*      mIoWrapper;
+    EAS_PCM*            mAudioBuffer;// EAS renders the MIDI data into this buffer,
+    sp<AudioTrack>      mAudioTrack; // and we play it in this audio track
+    int                 mTrackBufferSize;
+    S_JET_STATUS        mJetStatus;
+    S_JET_STATUS        mPreviousJetStatus;
+
+    class JetPlayerThread : public Thread {
+    public:
+        JetPlayerThread(JetPlayer *player) : mPlayer(player) {
+        }
+
+    protected:
+        virtual ~JetPlayerThread() {}
+
+    private:
+        JetPlayer *mPlayer;
+
+        bool threadLoop() {
+            int result;
+            result = mPlayer->render();
+            return false;
+        }
+
+        JetPlayerThread(const JetPlayerThread &);
+        JetPlayerThread &operator=(const JetPlayerThread &);
+    };
+
+    sp<JetPlayerThread> mThread;
+
+}; // end class JetPlayer
+
+} // end namespace android
+
+
+
+#endif /*JETPLAYER_H_*/
diff --git a/core/jni/android_media_JetPlayer.cpp b/media/jni/android_media_JetPlayer.cpp
similarity index 99%
rename from core/jni/android_media_JetPlayer.cpp
rename to media/jni/android_media_JetPlayer.cpp
index da116bf..8a05f85 100644
--- a/core/jni/android_media_JetPlayer.cpp
+++ b/media/jni/android_media_JetPlayer.cpp
@@ -27,7 +27,7 @@
 #include "core_jni_helpers.h"
 
 #include <utils/Log.h>
-#include <media/JetPlayer.h>
+#include "JetPlayer.h"
 
 
 using namespace android;
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index d24edc7..b4fa07b 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1436,6 +1436,7 @@
 }
 extern int register_android_media_ImageReader(JNIEnv *env);
 extern int register_android_media_ImageWriter(JNIEnv *env);
+extern int register_android_media_JetPlayer(JNIEnv *env);
 extern int register_android_media_Crypto(JNIEnv *env);
 extern int register_android_media_Drm(JNIEnv *env);
 extern int register_android_media_Descrambler(JNIEnv *env);
@@ -1446,7 +1447,6 @@
 extern int register_android_media_MediaMetadataRetriever(JNIEnv *env);
 extern int register_android_media_MediaMuxer(JNIEnv *env);
 extern int register_android_media_MediaRecorder(JNIEnv *env);
-extern int register_android_media_MediaScanner(JNIEnv *env);
 extern int register_android_media_MediaSync(JNIEnv *env);
 extern int register_android_media_ResampleInputStream(JNIEnv *env);
 extern int register_android_media_MediaProfiles(JNIEnv *env);
@@ -1475,6 +1475,11 @@
         goto bail;
     }
 
+    if (register_android_media_JetPlayer(env) < 0) {
+        ALOGE("ERROR: JetPlayer native registration failed");
+        goto bail;
+    }
+
     if (register_android_media_MediaPlayer(env) < 0) {
         ALOGE("ERROR: MediaPlayer native registration failed\n");
         goto bail;
@@ -1485,11 +1490,6 @@
         goto bail;
     }
 
-    if (register_android_media_MediaScanner(env) < 0) {
-        ALOGE("ERROR: MediaScanner native registration failed\n");
-        goto bail;
-    }
-
     if (register_android_media_MediaMetadataRetriever(env) < 0) {
         ALOGE("ERROR: MediaMetadataRetriever native registration failed\n");
         goto bail;
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
deleted file mode 100644
index 58044c0..0000000
--- a/media/jni/android_media_MediaScanner.cpp
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
-**
-** Copyright 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.
-*/
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaScannerJNI"
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <media/mediascanner.h>
-#include <media/stagefright/StagefrightMediaScanner.h>
-#include <private/media/VideoFrame.h>
-
-#include "jni.h"
-#include <nativehelper/JNIHelp.h>
-#include "android_runtime/AndroidRuntime.h"
-#include "android_runtime/Log.h"
-#include <android-base/macros.h>                // for FALLTHROUGH_INTENDED
-
-using namespace android;
-
-
-static const char* const kClassMediaScannerClient =
-        "android/media/MediaScannerClient";
-
-static const char* const kClassMediaScanner =
-        "android/media/MediaScanner";
-
-static const char* const kRunTimeException =
-        "java/lang/RuntimeException";
-
-static const char* const kIllegalArgumentException =
-        "java/lang/IllegalArgumentException";
-
-struct fields_t {
-    jfieldID    context;
-};
-static fields_t fields;
-
-static status_t checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
-    if (env->ExceptionCheck()) {
-        ALOGE("An exception was thrown by callback '%s'.", methodName);
-        LOGE_EX(env);
-        env->ExceptionClear();
-        return UNKNOWN_ERROR;
-    }
-    return OK;
-}
-
-// stolen from dalvik/vm/checkJni.cpp
-static bool isValidUtf8(const char* bytes) {
-    while (*bytes != '\0') {
-        unsigned char utf8 = *(bytes++);
-        // Switch on the high four bits.
-        switch (utf8 >> 4) {
-        case 0x00:
-        case 0x01:
-        case 0x02:
-        case 0x03:
-        case 0x04:
-        case 0x05:
-        case 0x06:
-        case 0x07:
-            // Bit pattern 0xxx. No need for any extra bytes.
-            break;
-        case 0x08:
-        case 0x09:
-        case 0x0a:
-        case 0x0b:
-        case 0x0f:
-            /*
-             * Bit pattern 10xx or 1111, which are illegal start bytes.
-             * Note: 1111 is valid for normal UTF-8, but not the
-             * modified UTF-8 used here.
-             */
-            return false;
-        case 0x0e:
-            // Bit pattern 1110, so there are two additional bytes.
-            utf8 = *(bytes++);
-            if ((utf8 & 0xc0) != 0x80) {
-                return false;
-            }
-            // Fall through to take care of the final byte.
-            FALLTHROUGH_INTENDED;
-        case 0x0c:
-        case 0x0d:
-            // Bit pattern 110x, so there is one additional byte.
-            utf8 = *(bytes++);
-            if ((utf8 & 0xc0) != 0x80) {
-                return false;
-            }
-            break;
-        }
-    }
-    return true;
-}
-
-class MyMediaScannerClient : public MediaScannerClient
-{
-public:
-    MyMediaScannerClient(JNIEnv *env, jobject client)
-        :   mEnv(env),
-            mClient(env->NewGlobalRef(client)),
-            mScanFileMethodID(0),
-            mHandleStringTagMethodID(0),
-            mSetMimeTypeMethodID(0)
-    {
-        ALOGV("MyMediaScannerClient constructor");
-        jclass mediaScannerClientInterface =
-                env->FindClass(kClassMediaScannerClient);
-
-        if (mediaScannerClientInterface == NULL) {
-            ALOGE("Class %s not found", kClassMediaScannerClient);
-        } else {
-            mScanFileMethodID = env->GetMethodID(
-                                    mediaScannerClientInterface,
-                                    "scanFile",
-                                    "(Ljava/lang/String;JJZZ)V");
-
-            mHandleStringTagMethodID = env->GetMethodID(
-                                    mediaScannerClientInterface,
-                                    "handleStringTag",
-                                    "(Ljava/lang/String;Ljava/lang/String;)V");
-
-            mSetMimeTypeMethodID = env->GetMethodID(
-                                    mediaScannerClientInterface,
-                                    "setMimeType",
-                                    "(Ljava/lang/String;)V");
-        }
-    }
-
-    virtual ~MyMediaScannerClient()
-    {
-        ALOGV("MyMediaScannerClient destructor");
-        mEnv->DeleteGlobalRef(mClient);
-    }
-
-    virtual status_t scanFile(const char* path, long long lastModified,
-            long long fileSize, bool isDirectory, bool noMedia)
-    {
-        ALOGV("scanFile: path(%s), time(%lld), size(%lld) and isDir(%d)",
-            path, lastModified, fileSize, isDirectory);
-
-        jstring pathStr;
-        if ((pathStr = mEnv->NewStringUTF(path)) == NULL) {
-            mEnv->ExceptionClear();
-            return NO_MEMORY;
-        }
-
-        mEnv->CallVoidMethod(mClient, mScanFileMethodID, pathStr, lastModified,
-                fileSize, isDirectory, noMedia);
-
-        mEnv->DeleteLocalRef(pathStr);
-        return checkAndClearExceptionFromCallback(mEnv, "scanFile");
-    }
-
-    virtual status_t handleStringTag(const char* name, const char* value)
-    {
-        ALOGV("handleStringTag: name(%s) and value(%s)", name, value);
-        jstring nameStr, valueStr;
-        if ((nameStr = mEnv->NewStringUTF(name)) == NULL) {
-            mEnv->ExceptionClear();
-            return NO_MEMORY;
-        }
-        char *cleaned = NULL;
-        if (!isValidUtf8(value)) {
-            cleaned = strdup(value);
-            char *chp = cleaned;
-            char ch;
-            while ((ch = *chp)) {
-                if (ch & 0x80) {
-                    *chp = '?';
-                }
-                chp++;
-            }
-            value = cleaned;
-        }
-        valueStr = mEnv->NewStringUTF(value);
-        free(cleaned);
-        if (valueStr == NULL) {
-            mEnv->DeleteLocalRef(nameStr);
-            mEnv->ExceptionClear();
-            return NO_MEMORY;
-        }
-
-        mEnv->CallVoidMethod(
-            mClient, mHandleStringTagMethodID, nameStr, valueStr);
-
-        mEnv->DeleteLocalRef(nameStr);
-        mEnv->DeleteLocalRef(valueStr);
-        return checkAndClearExceptionFromCallback(mEnv, "handleStringTag");
-    }
-
-    virtual status_t setMimeType(const char* mimeType)
-    {
-        ALOGV("setMimeType: %s", mimeType);
-        jstring mimeTypeStr;
-        if ((mimeTypeStr = mEnv->NewStringUTF(mimeType)) == NULL) {
-            mEnv->ExceptionClear();
-            return NO_MEMORY;
-        }
-
-        mEnv->CallVoidMethod(mClient, mSetMimeTypeMethodID, mimeTypeStr);
-
-        mEnv->DeleteLocalRef(mimeTypeStr);
-        return checkAndClearExceptionFromCallback(mEnv, "setMimeType");
-    }
-
-private:
-    JNIEnv *mEnv;
-    jobject mClient;
-    jmethodID mScanFileMethodID;
-    jmethodID mHandleStringTagMethodID;
-    jmethodID mSetMimeTypeMethodID;
-};
-
-
-static MediaScanner *getNativeScanner_l(JNIEnv* env, jobject thiz)
-{
-    return (MediaScanner *) env->GetLongField(thiz, fields.context);
-}
-
-static void setNativeScanner_l(JNIEnv* env, jobject thiz, MediaScanner *s)
-{
-    env->SetLongField(thiz, fields.context, (jlong)s);
-}
-
-static void
-android_media_MediaScanner_processDirectory(
-        JNIEnv *env, jobject thiz, jstring path, jobject client)
-{
-    ALOGV("processDirectory");
-    MediaScanner *mp = getNativeScanner_l(env, thiz);
-    if (mp == NULL) {
-        jniThrowException(env, kRunTimeException, "No scanner available");
-        return;
-    }
-
-    if (path == NULL) {
-        jniThrowException(env, kIllegalArgumentException, NULL);
-        return;
-    }
-
-    const char *pathStr = env->GetStringUTFChars(path, NULL);
-    if (pathStr == NULL) {  // Out of memory
-        return;
-    }
-
-    MyMediaScannerClient myClient(env, client);
-    MediaScanResult result = mp->processDirectory(pathStr, myClient);
-    if (result == MEDIA_SCAN_RESULT_ERROR) {
-        ALOGE("An error occurred while scanning directory '%s'.", pathStr);
-    }
-    env->ReleaseStringUTFChars(path, pathStr);
-}
-
-static jboolean
-android_media_MediaScanner_processFile(
-        JNIEnv *env, jobject thiz, jstring path,
-        jstring mimeType, jobject client)
-{
-    ALOGV("processFile");
-
-    // Lock already hold by processDirectory
-    MediaScanner *mp = getNativeScanner_l(env, thiz);
-    if (mp == NULL) {
-        jniThrowException(env, kRunTimeException, "No scanner available");
-        return false;
-    }
-
-    if (path == NULL) {
-        jniThrowException(env, kIllegalArgumentException, NULL);
-        return false;
-    }
-
-    const char *pathStr = env->GetStringUTFChars(path, NULL);
-    if (pathStr == NULL) {  // Out of memory
-        return false;
-    }
-
-    const char *mimeTypeStr =
-        (mimeType ? env->GetStringUTFChars(mimeType, NULL) : NULL);
-    if (mimeType && mimeTypeStr == NULL) {  // Out of memory
-        // ReleaseStringUTFChars can be called with an exception pending.
-        env->ReleaseStringUTFChars(path, pathStr);
-        return false;
-    }
-
-    MyMediaScannerClient myClient(env, client);
-    MediaScanResult result = mp->processFile(pathStr, mimeTypeStr, myClient);
-    if (result == MEDIA_SCAN_RESULT_ERROR) {
-        ALOGE("An error occurred while scanning file '%s'.", pathStr);
-    }
-    env->ReleaseStringUTFChars(path, pathStr);
-    if (mimeType) {
-        env->ReleaseStringUTFChars(mimeType, mimeTypeStr);
-    }
-    return result != MEDIA_SCAN_RESULT_ERROR;
-}
-
-static void
-android_media_MediaScanner_setLocale(
-        JNIEnv *env, jobject thiz, jstring locale)
-{
-    ALOGV("setLocale");
-    MediaScanner *mp = getNativeScanner_l(env, thiz);
-    if (mp == NULL) {
-        jniThrowException(env, kRunTimeException, "No scanner available");
-        return;
-    }
-
-    if (locale == NULL) {
-        jniThrowException(env, kIllegalArgumentException, NULL);
-        return;
-    }
-    const char *localeStr = env->GetStringUTFChars(locale, NULL);
-    if (localeStr == NULL) {  // Out of memory
-        return;
-    }
-    mp->setLocale(localeStr);
-
-    env->ReleaseStringUTFChars(locale, localeStr);
-}
-
-static jbyteArray
-android_media_MediaScanner_extractAlbumArt(
-        JNIEnv *env, jobject thiz, jobject fileDescriptor)
-{
-    ALOGV("extractAlbumArt");
-    MediaScanner *mp = getNativeScanner_l(env, thiz);
-    if (mp == NULL) {
-        jniThrowException(env, kRunTimeException, "No scanner available");
-        return NULL;
-    }
-
-    if (fileDescriptor == NULL) {
-        jniThrowException(env, kIllegalArgumentException, NULL);
-        return NULL;
-    }
-
-    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    MediaAlbumArt* mediaAlbumArt = mp->extractAlbumArt(fd);
-    if (mediaAlbumArt == NULL) {
-        return NULL;
-    }
-
-    jbyteArray array = env->NewByteArray(mediaAlbumArt->size());
-    if (array != NULL) {
-        const jbyte* data =
-                reinterpret_cast<const jbyte*>(mediaAlbumArt->data());
-        env->SetByteArrayRegion(array, 0, mediaAlbumArt->size(), data);
-    }
-
-    free(mediaAlbumArt);
-    // if NewByteArray() returned NULL, an out-of-memory
-    // exception will have been raised. I just want to
-    // return null in that case.
-    env->ExceptionClear();
-    return array;
-}
-
-// This function gets a field ID, which in turn causes class initialization.
-// It is called from a static block in MediaScanner, which won't run until the
-// first time an instance of this class is used.
-static void
-android_media_MediaScanner_native_init(JNIEnv *env)
-{
-    ALOGV("native_init");
-    jclass clazz = env->FindClass(kClassMediaScanner);
-    if (clazz == NULL) {
-        return;
-    }
-
-    fields.context = env->GetFieldID(clazz, "mNativeContext", "J");
-    if (fields.context == NULL) {
-        return;
-    }
-}
-
-static void
-android_media_MediaScanner_native_setup(JNIEnv *env, jobject thiz)
-{
-    ALOGV("native_setup");
-    MediaScanner *mp = new StagefrightMediaScanner;
-
-    if (mp == NULL) {
-        jniThrowException(env, kRunTimeException, "Out of memory");
-        return;
-    }
-
-    env->SetLongField(thiz, fields.context, (jlong)mp);
-}
-
-static void
-android_media_MediaScanner_native_finalize(JNIEnv *env, jobject thiz)
-{
-    ALOGV("native_finalize");
-    MediaScanner *mp = getNativeScanner_l(env, thiz);
-    if (mp == 0) {
-        return;
-    }
-    delete mp;
-    setNativeScanner_l(env, thiz, 0);
-}
-
-static const JNINativeMethod gMethods[] = {
-    {
-        "processDirectory",
-        "(Ljava/lang/String;Landroid/media/MediaScannerClient;)V",
-        (void *)android_media_MediaScanner_processDirectory
-    },
-
-    {
-        "processFile",
-        "(Ljava/lang/String;Ljava/lang/String;Landroid/media/MediaScannerClient;)Z",
-        (void *)android_media_MediaScanner_processFile
-    },
-
-    {
-        "setLocale",
-        "(Ljava/lang/String;)V",
-        (void *)android_media_MediaScanner_setLocale
-    },
-
-    {
-        "extractAlbumArt",
-        "(Ljava/io/FileDescriptor;)[B",
-        (void *)android_media_MediaScanner_extractAlbumArt
-    },
-
-    {
-        "native_init",
-        "()V",
-        (void *)android_media_MediaScanner_native_init
-    },
-
-    {
-        "native_setup",
-        "()V",
-        (void *)android_media_MediaScanner_native_setup
-    },
-
-    {
-        "native_finalize",
-        "()V",
-        (void *)android_media_MediaScanner_native_finalize
-    },
-};
-
-// This function only registers the native methods, and is called from
-// JNI_OnLoad in android_media_MediaPlayer.cpp
-int register_android_media_MediaScanner(JNIEnv *env)
-{
-    return AndroidRuntime::registerNativeMethods(env,
-                kClassMediaScanner, gMethods, NELEM(gMethods));
-}
diff --git a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
index 8d39a93..f4f8d0b 100644
--- a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
@@ -26,7 +26,7 @@
 import java.util.Map;
 
 public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService {
-    private static final String TAG = "SampleMediaRoute2Serv";
+    private static final String TAG = "SampleMR2ProviderSvc";
 
     public static final String ROUTE_ID1 = "route_id1";
     public static final String ROUTE_NAME1 = "Sample Route 1";
@@ -130,6 +130,33 @@
         }
     }
 
+    @Override
+    public void onSetVolume(String routeId, int volume) {
+        MediaRoute2Info route = mRoutes.get(routeId);
+        if (route == null) {
+            return;
+        }
+        volume = Math.min(volume, Math.max(0, route.getVolumeMax()));
+        mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
+                .setVolume(volume)
+                .build());
+        publishRoutes();
+    }
+
+    @Override
+    public void onUpdateVolume(String routeId, int delta) {
+        MediaRoute2Info route = mRoutes.get(routeId);
+        if (route == null) {
+            return;
+        }
+        int volume = route.getVolume() + delta;
+        volume = Math.min(volume, Math.max(0, route.getVolumeMax()));
+        mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
+                .setVolume(volume)
+                .build());
+        publishRoutes();
+    }
+
     void publishRoutes() {
         MediaRoute2ProviderInfo info = new MediaRoute2ProviderInfo.Builder()
                 .addRoutes(mRoutes.values())
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index da832ac..ca43d04 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -47,8 +47,10 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -190,17 +192,8 @@
         MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class);
         mManager.registerCallback(mExecutor, mockCallback);
 
-        MediaRouter2.Callback mockRouterCallback = mock(MediaRouter2.Callback.class);
-
-        mRouter2.setControlCategories(CONTROL_CATEGORIES_SPECIAL);
-        mRouter2.registerCallback(mExecutor, mockRouterCallback);
-        mRouter2.unregisterCallback(mockRouterCallback);
-
-        verify(mockCallback, timeout(TIMEOUT_MS))
-                .onRoutesChanged(argThat(routes -> routes.size() > 0));
-
         Map<String, MediaRoute2Info> routes =
-                createRouteMap(mManager.getAvailableRoutes(mPackageName));
+                waitAndGetRoutesWithManager(CONTROL_CATEGORIES_SPECIAL);
 
         Assert.assertEquals(1, routes.size());
         Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
@@ -214,12 +207,10 @@
     @Test
     public void testGetRoutes() throws Exception {
         MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
-
-        mRouter2.setControlCategories(CONTROL_CATEGORIES_SPECIAL);
         mRouter2.registerCallback(mExecutor, mockCallback);
-        verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
-                .onRoutesChanged(argThat(routes -> routes.size() > 0));
-        Map<String, MediaRoute2Info> routes = createRouteMap(mRouter2.getRoutes());
+
+        Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CONTROL_CATEGORIES_SPECIAL);
+
         Assert.assertEquals(1, routes.size());
         Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
 
@@ -228,51 +219,40 @@
 
     @Test
     public void testOnRouteSelected() throws Exception {
-        MediaRouter2.Callback mockRouterCallback = mock(MediaRouter2.Callback.class);
+        MediaRouter2.Callback routerCallback = new MediaRouter2.Callback();
         MediaRouter2Manager.Callback managerCallback = mock(MediaRouter2Manager.Callback.class);
 
         mManager.registerCallback(mExecutor, managerCallback);
-        mRouter2.setControlCategories(CONTROL_CATEGORIES_ALL);
-        mRouter2.registerCallback(mExecutor, mockRouterCallback);
+        mRouter2.registerCallback(mExecutor, routerCallback);
 
-        verify(managerCallback, timeout(TIMEOUT_MS))
-                .onRoutesChanged(argThat(routes -> routes.size() > 0));
-
-        Map<String, MediaRoute2Info> routes =
-                createRouteMap(mManager.getAvailableRoutes(mPackageName));
+        Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CONTROL_CATEGORIES_ALL);
 
         MediaRoute2Info routeToSelect = routes.get(ROUTE_ID1);
-        mManager.selectRoute(mPackageName, routeToSelect);
-
         assertNotNull(routeToSelect);
+
+        mManager.selectRoute(mPackageName, routeToSelect);
         verify(managerCallback, timeout(TIMEOUT_MS))
                 .onRouteAdded(argThat(route -> route.equals(routeToSelect)));
 
+        mRouter2.unregisterCallback(routerCallback);
         mManager.unregisterCallback(managerCallback);
-        mRouter2.unregisterCallback(mockRouterCallback);
     }
 
     /**
      * Tests selecting and unselecting routes of a single provider.
      */
     @Test
-    public void testSingleProviderSelect() {
+    public void testSingleProviderSelect() throws Exception {
         MediaRouter2Manager.Callback managerCallback = mock(MediaRouter2Manager.Callback.class);
         MediaRouter2.Callback routerCallback = mock(MediaRouter2.Callback.class);
 
         mManager.registerCallback(mExecutor, managerCallback);
-        mRouter2.setControlCategories(CONTROL_CATEGORIES_ALL);
         mRouter2.registerCallback(mExecutor, routerCallback);
 
-        verify(managerCallback, timeout(TIMEOUT_MS))
-                .onRoutesChanged(argThat(routes -> routes.size() > 0));
-
-        Map<String, MediaRoute2Info> routes =
-                createRouteMap(mManager.getAvailableRoutes(mPackageName));
+        Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CONTROL_CATEGORIES_ALL);
 
         mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1));
-        verify(managerCallback, timeout(TIMEOUT_MS)
-        )
+        verify(managerCallback, timeout(TIMEOUT_MS))
                 .onRouteChanged(argThat(routeInfo -> TextUtils.equals(ROUTE_ID1, routeInfo.getId())
                         && TextUtils.equals(routeInfo.getClientPackageName(), mPackageName)));
 
@@ -291,14 +271,67 @@
     }
 
     @Test
-    public void testVolumeHandling() {
+    public void testControlVolumeWithRouter() throws Exception {
         MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
 
-        mRouter2.setControlCategories(CONTROL_CATEGORIES_ALL);
+        Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CONTROL_CATEGORIES_ALL);
         mRouter2.registerCallback(mExecutor, mockCallback);
+
+        MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
+        int originalVolume = volRoute.getVolume();
+        int deltaVolume = (originalVolume == volRoute.getVolumeMax() ? -1 : 1);
+        int targetVolume = originalVolume + deltaVolume;
+
+        mRouter2.requestSetVolume(volRoute, targetVolume);
         verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
-                .onRoutesChanged(argThat(routes -> routes.size() > 0));
-        Map<String, MediaRoute2Info> routes = createRouteMap(mRouter2.getRoutes());
+                .onRouteChanged(argThat(route ->
+                        route.getId().equals(volRoute.getId())
+                                && route.getVolume() == targetVolume));
+
+        mRouter2.requestUpdateVolume(volRoute, -deltaVolume);
+        verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
+                .onRouteChanged(argThat(route ->
+                        route.getId().equals(volRoute.getId())
+                                && route.getVolume() == originalVolume));
+
+        mRouter2.unregisterCallback(mockCallback);
+    }
+
+    @Test
+    public void testControlVolumeWithManager() throws Exception {
+        MediaRouter2Manager.Callback managerCallback = mock(MediaRouter2Manager.Callback.class);
+        MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
+
+        mManager.registerCallback(mExecutor, managerCallback);
+        mRouter2.registerCallback(mExecutor, mockCallback);
+        Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CONTROL_CATEGORIES_ALL);
+
+        MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
+        int originalVolume = volRoute.getVolume();
+        int deltaVolume = (originalVolume == volRoute.getVolumeMax() ? -1 : 1);
+        int targetVolume = originalVolume + deltaVolume;
+
+        mManager.requestSetVolume(volRoute, targetVolume);
+        verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
+                .onRouteChanged(argThat(route ->
+                        route.getId().equals(volRoute.getId())
+                                && route.getVolume() == targetVolume));
+
+        mManager.requestUpdateVolume(volRoute, -deltaVolume);
+        verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
+                .onRouteChanged(argThat(route ->
+                        route.getId().equals(volRoute.getId())
+                                && route.getVolume() == originalVolume));
+
+        mRouter2.unregisterCallback(mockCallback);
+        mManager.unregisterCallback(managerCallback);
+    }
+
+    @Test
+    public void testVolumeHandling() throws Exception {
+        MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
+        mRouter2.registerCallback(mExecutor, mockCallback);
+        Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CONTROL_CATEGORIES_ALL);
 
         MediaRoute2Info fixedVolumeRoute = routes.get(ROUTE_ID_FIXED_VOLUME);
         MediaRoute2Info variableVolumeRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
@@ -310,6 +343,48 @@
         mRouter2.unregisterCallback(mockCallback);
     }
 
+    Map<String, MediaRoute2Info> waitAndGetRoutes(List<String> controlCategories) throws Exception {
+        CountDownLatch latch = new CountDownLatch(1);
+        MediaRouter2.Callback callback = new MediaRouter2.Callback() {
+            @Override
+            public void onRoutesChanged(List<MediaRoute2Info> routes) {
+                if (routes.size() > 0) latch.countDown();
+            }
+        };
+        mRouter2.setControlCategories(controlCategories);
+        mRouter2.registerCallback(mExecutor, callback);
+        try {
+            latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+            return createRouteMap(mRouter2.getRoutes());
+        } finally {
+            mRouter2.unregisterCallback(callback);
+        }
+    }
+
+    Map<String, MediaRoute2Info> waitAndGetRoutesWithManager(List<String> controlCategories)
+            throws Exception {
+        CountDownLatch latch = new CountDownLatch(1);
+
+        // Dummy callback is required to send control category info.
+        MediaRouter2.Callback routerCallback = new MediaRouter2.Callback();
+        MediaRouter2Manager.Callback managerCallback = new MediaRouter2Manager.Callback() {
+            @Override
+            public void onRoutesChanged(List<MediaRoute2Info> routes) {
+                if (routes.size() > 0) latch.countDown();
+            }
+        };
+        mManager.registerCallback(mExecutor, managerCallback);
+        mRouter2.setControlCategories(controlCategories);
+        mRouter2.registerCallback(mExecutor, routerCallback);
+        try {
+            latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+            return createRouteMap(mManager.getAvailableRoutes(mPackageName));
+        } finally {
+            mRouter2.unregisterCallback(routerCallback);
+            mManager.unregisterCallback(managerCallback);
+        }
+    }
+
     // Helper for getting routes easily
     static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
         Map<String, MediaRoute2Info> routeMap = new HashMap<>();
diff --git a/packages/BackupEncryption/Android.bp b/packages/BackupEncryption/Android.bp
index 342d796..68e937c 100644
--- a/packages/BackupEncryption/Android.bp
+++ b/packages/BackupEncryption/Android.bp
@@ -17,8 +17,7 @@
 android_app {
     name: "BackupEncryption",
     srcs: ["src/**/*.java"],
-    libs: ["backup-encryption-protos"],
-    static_libs: ["backuplib"],
+    static_libs: ["backup-encryption-protos", "backuplib"],
     optimize: { enabled: false },
     platform_apis: true,
     certificate: "platform",
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/EncryptionKeyHelper.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/EncryptionKeyHelper.java
new file mode 100644
index 0000000..2035b66
--- /dev/null
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/EncryptionKeyHelper.java
@@ -0,0 +1,81 @@
+/*
+ * 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.server.backup.encryption;
+
+import android.content.Context;
+import android.security.keystore.recovery.InternalRecoveryServiceException;
+import android.security.keystore.recovery.RecoveryController;
+
+import com.android.server.backup.encryption.keys.RecoverableKeyStoreSecondaryKey;
+import com.android.server.backup.encryption.keys.RecoverableKeyStoreSecondaryKeyManager;
+import com.android.server.backup.encryption.keys.TertiaryKeyManager;
+import com.android.server.backup.encryption.keys.TertiaryKeyRotationScheduler;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+
+class EncryptionKeyHelper {
+    private static SecureRandom sSecureRandom = new  SecureRandom();
+
+    private final Context mContext;
+    private final RecoverableKeyStoreSecondaryKeyManager
+            .RecoverableKeyStoreSecondaryKeyManagerProvider
+            mSecondaryKeyManagerProvider;
+
+    EncryptionKeyHelper(Context context) {
+        mContext = context;
+        mSecondaryKeyManagerProvider =
+                () ->
+                        new RecoverableKeyStoreSecondaryKeyManager(
+                                RecoveryController.getInstance(mContext), sSecureRandom);
+    }
+
+    RecoverableKeyStoreSecondaryKeyManager
+            .RecoverableKeyStoreSecondaryKeyManagerProvider getKeyManagerProvider() {
+        return mSecondaryKeyManagerProvider;
+    }
+
+    RecoverableKeyStoreSecondaryKey getActiveSecondaryKey()
+            throws UnrecoverableKeyException, InternalRecoveryServiceException {
+        String keyAlias = CryptoSettings.getInstance(mContext).getActiveSecondaryKeyAlias().get();
+        return mSecondaryKeyManagerProvider.get().get(keyAlias).get();
+    }
+
+    SecretKey getTertiaryKey(
+            String packageName,
+            RecoverableKeyStoreSecondaryKey secondaryKey)
+            throws IllegalBlockSizeException, InvalidAlgorithmParameterException,
+            NoSuchAlgorithmException, IOException, NoSuchPaddingException,
+            InvalidKeyException {
+        TertiaryKeyManager tertiaryKeyManager =
+                new TertiaryKeyManager(
+                        mContext,
+                        sSecureRandom,
+                        TertiaryKeyRotationScheduler.getInstance(mContext),
+                        secondaryKey,
+                        packageName);
+        return tertiaryKeyManager.getKey();
+    }
+}
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/KeyValueEncrypter.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/KeyValueEncrypter.java
new file mode 100644
index 0000000..1d841b4
--- /dev/null
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/KeyValueEncrypter.java
@@ -0,0 +1,143 @@
+/*
+ * 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.server.backup.encryption;
+
+import static com.android.server.backup.encryption.BackupEncryptionService.TAG;
+
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import com.android.server.backup.encryption.client.CryptoBackupServer;
+import com.android.server.backup.encryption.keys.KeyWrapUtils;
+import com.android.server.backup.encryption.keys.RecoverableKeyStoreSecondaryKey;
+import com.android.server.backup.encryption.protos.nano.WrappedKeyProto;
+import com.android.server.backup.encryption.tasks.EncryptedKvBackupTask;
+import com.android.server.backup.encryption.tasks.EncryptedKvRestoreTask;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.SecureRandom;
+import java.util.Map;
+
+public class KeyValueEncrypter {
+    private final Context mContext;
+    private final EncryptionKeyHelper mKeyHelper;
+
+    public KeyValueEncrypter(Context context) {
+        mContext = context;
+        mKeyHelper = new EncryptionKeyHelper(mContext);
+    }
+
+    public void encryptKeyValueData(
+            String packageName, ParcelFileDescriptor inputFd, OutputStream outputStream)
+            throws Exception {
+        EncryptedKvBackupTask.EncryptedKvBackupTaskFactory backupTaskFactory =
+                new EncryptedKvBackupTask.EncryptedKvBackupTaskFactory();
+        EncryptedKvBackupTask backupTask =
+                backupTaskFactory.newInstance(
+                        mContext,
+                        new SecureRandom(),
+                        new FileBackupServer(outputStream),
+                        CryptoSettings.getInstance(mContext),
+                        mKeyHelper.getKeyManagerProvider(),
+                        inputFd,
+                        packageName);
+        backupTask.performBackup(/* incremental */ false);
+    }
+
+    public void decryptKeyValueData(String packageName,
+            InputStream encryptedInputStream, ParcelFileDescriptor outputFd) throws Exception {
+        RecoverableKeyStoreSecondaryKey secondaryKey = mKeyHelper.getActiveSecondaryKey();
+
+        EncryptedKvRestoreTask.EncryptedKvRestoreTaskFactory restoreTaskFactory =
+                new EncryptedKvRestoreTask.EncryptedKvRestoreTaskFactory();
+        EncryptedKvRestoreTask restoreTask =
+                restoreTaskFactory.newInstance(
+                        mContext,
+                        mKeyHelper.getKeyManagerProvider(),
+                        new InputStreamFullRestoreDownloader(encryptedInputStream),
+                        secondaryKey.getAlias(),
+                        KeyWrapUtils.wrap(
+                                secondaryKey.getSecretKey(),
+                                mKeyHelper.getTertiaryKey(packageName, secondaryKey)));
+
+        restoreTask.getRestoreData(outputFd);
+    }
+
+    // TODO(b/142455725): Extract into a commong class.
+    private static class FileBackupServer implements CryptoBackupServer {
+        private static final String EMPTY_DOC_ID = "";
+
+        private final OutputStream mOutputStream;
+
+        FileBackupServer(OutputStream outputStream) {
+            mOutputStream = outputStream;
+        }
+
+        @Override
+        public String uploadIncrementalBackup(
+                String packageName,
+                String oldDocId,
+                byte[] diffScript,
+                WrappedKeyProto.WrappedKey tertiaryKey) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public String uploadNonIncrementalBackup(
+                String packageName, byte[] data, WrappedKeyProto.WrappedKey tertiaryKey) {
+            try {
+                mOutputStream.write(data);
+            } catch (IOException e) {
+                Log.w(TAG, "Failed to write encrypted data to file: ", e);
+            }
+
+            return EMPTY_DOC_ID;
+        }
+
+        @Override
+        public void setActiveSecondaryKeyAlias(
+                String keyAlias, Map<String, WrappedKeyProto.WrappedKey> tertiaryKeys) {
+            // Do nothing.
+        }
+    }
+
+    // TODO(b/142455725): Extract into a commong class.
+    private static class InputStreamFullRestoreDownloader extends FullRestoreDownloader {
+        private final InputStream mInputStream;
+
+        InputStreamFullRestoreDownloader(InputStream inputStream) {
+            mInputStream = inputStream;
+        }
+
+        @Override
+        public int readNextChunk(byte[] buffer) throws IOException {
+            return mInputStream.read(buffer);
+        }
+
+        @Override
+        public void finish(FinishType finishType) {
+            try {
+                mInputStream.close();
+            } catch (IOException e) {
+                Log.w(TAG, "Error while reading restore data");
+            }
+        }
+    }
+}
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransport.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransport.java
index 1d0224d..c3cb335 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransport.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransport.java
@@ -18,27 +18,58 @@
 
 import static com.android.server.backup.encryption.BackupEncryptionService.TAG;
 
+import android.app.backup.BackupTransport;
+import android.app.backup.RestoreDescription;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.backup.IBackupTransport;
+import com.android.server.backup.encryption.KeyValueEncrypter;
 import com.android.server.backup.transport.DelegatingTransport;
 import com.android.server.backup.transport.TransportClient;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.concurrent.atomic.AtomicReference;
+
 /**
  * This is an implementation of {@link IBackupTransport} that encrypts (or decrypts) the data when
  * sending it (or receiving it) from the {@link IBackupTransport} returned by {@link
  * TransportClient.connect(String)}.
  */
 public class IntermediateEncryptingTransport extends DelegatingTransport {
+    private static final String BACKUP_TEMP_DIR = "backup";
+    private static final String RESTORE_TEMP_DIR = "restore";
+
     private final TransportClient mTransportClient;
     private final Object mConnectLock = new Object();
+    private final Context mContext;
     private volatile IBackupTransport mRealTransport;
+    private AtomicReference<String> mNextRestorePackage = new AtomicReference<>();
+    private final KeyValueEncrypter mKeyValueEncrypter;
+    private final boolean mShouldEncrypt;
+
+    IntermediateEncryptingTransport(
+            TransportClient transportClient, Context context, boolean shouldEncrypt) {
+        this(transportClient, context, new KeyValueEncrypter(context), shouldEncrypt);
+    }
 
     @VisibleForTesting
-    IntermediateEncryptingTransport(TransportClient transportClient) {
+    IntermediateEncryptingTransport(
+            TransportClient transportClient, Context context, KeyValueEncrypter keyValueEncrypter,
+            boolean shouldEncrypt) {
         mTransportClient = transportClient;
+        mContext = context;
+        mKeyValueEncrypter = keyValueEncrypter;
+        mShouldEncrypt = shouldEncrypt;
     }
 
     @Override
@@ -46,9 +77,116 @@
         if (mRealTransport == null) {
             connect();
         }
+        Log.d(TAG, "real transport = " + mRealTransport.name());
         return mRealTransport;
     }
 
+    @Override
+    public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd, int flags)
+            throws RemoteException {
+        if (!mShouldEncrypt) {
+            return super.performBackup(packageInfo, inFd, flags);
+        }
+
+        File encryptedStorageFile = getBackupTempStorage(packageInfo.packageName);
+        if (encryptedStorageFile == null) {
+            return BackupTransport.TRANSPORT_ERROR;
+        }
+
+        // Encrypt the backup data and write it into a temp file.
+        try (OutputStream encryptedOutput = new FileOutputStream(encryptedStorageFile)) {
+            mKeyValueEncrypter.encryptKeyValueData(packageInfo.packageName, inFd,
+                    encryptedOutput);
+        } catch (Throwable e) {
+            Log.e(TAG, "Failed to encrypt backup data: ", e);
+            return BackupTransport.TRANSPORT_ERROR;
+        }
+
+        // Pass the temp file to the real transport for backup.
+        try (FileInputStream encryptedInput = new FileInputStream(encryptedStorageFile)) {
+            return super.performBackup(
+                    packageInfo, ParcelFileDescriptor.dup(encryptedInput.getFD()), flags);
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to read encrypted data from temp storage: ", e);
+            return BackupTransport.TRANSPORT_ERROR;
+        }
+    }
+
+    @Override
+    public int getRestoreData(ParcelFileDescriptor outFd) throws RemoteException {
+        if (!mShouldEncrypt) {
+            return super.getRestoreData(outFd);
+        }
+
+        String nextRestorePackage = mNextRestorePackage.get();
+        if (nextRestorePackage == null) {
+            Log.e(TAG, "No next restore package set");
+            return BackupTransport.TRANSPORT_ERROR;
+        }
+
+        File encryptedStorageFile = getRestoreTempStorage(nextRestorePackage);
+        if (encryptedStorageFile == null) {
+            return BackupTransport.TRANSPORT_ERROR;
+        }
+
+        // Get encrypted restore data from the real transport and write it into a temp file.
+        try (FileOutputStream outputStream = new FileOutputStream(encryptedStorageFile)) {
+            int status = super.getRestoreData(ParcelFileDescriptor.dup(outputStream.getFD()));
+            if (status != BackupTransport.TRANSPORT_OK) {
+                Log.e(TAG, "Failed to read restore data from transport, status = " + status);
+                return status;
+            }
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to write encrypted data to temp storage: ", e);
+            return BackupTransport.TRANSPORT_ERROR;
+        }
+
+        // Decrypt the data and write it into the fd given by the real transport.
+        try (InputStream inputStream = new FileInputStream(encryptedStorageFile)) {
+            mKeyValueEncrypter.decryptKeyValueData(nextRestorePackage, inputStream, outFd);
+            encryptedStorageFile.delete();
+        } catch (Exception e) {
+            Log.e(TAG, "Failed to decrypt restored data: ", e);
+            return BackupTransport.TRANSPORT_ERROR;
+        }
+
+        return BackupTransport.TRANSPORT_OK;
+    }
+
+    @Override
+    public RestoreDescription nextRestorePackage() throws RemoteException {
+        if (!mShouldEncrypt) {
+            return super.nextRestorePackage();
+        }
+
+        RestoreDescription restoreDescription = super.nextRestorePackage();
+        mNextRestorePackage.set(restoreDescription.getPackageName());
+
+        return restoreDescription;
+    }
+
+    @VisibleForTesting
+    protected File getBackupTempStorage(String packageName) {
+        return getTempStorage(packageName, BACKUP_TEMP_DIR);
+    }
+
+    @VisibleForTesting
+    protected File getRestoreTempStorage(String packageName) {
+        return getTempStorage(packageName, RESTORE_TEMP_DIR);
+    }
+
+    private File getTempStorage(String packageName, String operationType) {
+        File encryptedDir = new File(mContext.getFilesDir(), operationType);
+        encryptedDir.mkdir();
+        File encryptedFile = new File(encryptedDir, packageName);
+        try {
+            encryptedFile.createNewFile();
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to create temp file for encrypted data: ", e);
+        }
+        return encryptedFile;
+    }
+
     private void connect() throws RemoteException {
         Log.i(TAG, "connecting " + mTransportClient);
         synchronized (mConnectLock) {
@@ -65,4 +203,9 @@
     TransportClient getClient() {
         return mTransportClient;
     }
+
+    @VisibleForTesting
+    void setNextRestorePackage(String nextRestorePackage) {
+        mNextRestorePackage.set(nextRestorePackage);
+    }
 }
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManager.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManager.java
index 6e6d571..7c4082c 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManager.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManager.java
@@ -26,20 +26,20 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.backup.IBackupTransport;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.server.backup.transport.TransportClientManager;
 import com.android.server.backup.transport.TransportStats;
 
 import java.util.HashMap;
 import java.util.Map;
 
-/**
- * Handles creation and cleanup of {@link IntermediateEncryptingTransport} instances.
- */
+/** Handles creation and cleanup of {@link IntermediateEncryptingTransport} instances. */
 public class IntermediateEncryptingTransportManager {
     private static final String CALLER = "IntermediateEncryptingTransportManager";
     private final TransportClientManager mTransportClientManager;
     private final Object mTransportsLock = new Object();
     private final Map<ComponentName, IntermediateEncryptingTransport> mTransports = new HashMap<>();
+    private Context mContext;
 
     @VisibleForTesting
     IntermediateEncryptingTransportManager(TransportClientManager transportClientManager) {
@@ -48,6 +48,7 @@
 
     public IntermediateEncryptingTransportManager(Context context) {
         this(new TransportClientManager(UserHandle.myUserId(), context, new TransportStats()));
+        mContext = context;
     }
 
     /**
@@ -55,31 +56,42 @@
      * provide a {@link IntermediateEncryptingTransport} which is an implementation of {@link
      * IBackupTransport} that encrypts (or decrypts) the data when sending it (or receiving it) from
      * the real {@link IBackupTransport}.
+     *
      * @param intent {@link Intent} created with a call to {@link
-     * TransportClientManager.getEncryptingTransportIntent(ComponentName)}.
+     *     TransportClientManager.getEncryptingTransportIntent(ComponentName)}.
      * @return
      */
     public IntermediateEncryptingTransport get(Intent intent) {
         Intent transportIntent = TransportClientManager.getRealTransportIntent(intent);
         Log.i(TAG, "get: intent:" + intent + " transportIntent:" + transportIntent);
         synchronized (mTransportsLock) {
-            return mTransports.computeIfAbsent(transportIntent.getComponent(),
-                    c -> create(transportIntent));
+            return mTransports.computeIfAbsent(
+                    transportIntent.getComponent(), c -> create(transportIntent));
         }
     }
 
-    /**
-     * Create an instance of {@link IntermediateEncryptingTransport}.
-     */
+    /** Create an instance of {@link IntermediateEncryptingTransport}. */
     private IntermediateEncryptingTransport create(Intent realTransportIntent) {
         Log.d(TAG, "create: intent:" + realTransportIntent);
-        return new IntermediateEncryptingTransport(mTransportClientManager.getTransportClient(
-                realTransportIntent.getComponent(), realTransportIntent.getExtras(), CALLER));
+
+        LockPatternUtils patternUtils = new LockPatternUtils(mContext);
+        boolean shouldEncrypt =
+                realTransportIntent.getComponent().getClassName().contains("EncryptedLocalTransport")
+                        && (patternUtils.isLockPatternEnabled(UserHandle.myUserId())
+                                || patternUtils.isLockPasswordEnabled(UserHandle.myUserId()));
+
+        return new IntermediateEncryptingTransport(
+                mTransportClientManager.getTransportClient(
+                        realTransportIntent.getComponent(),
+                        realTransportIntent.getExtras(),
+                        CALLER),
+                mContext,
+                shouldEncrypt);
     }
 
     /**
-     * Cleanup the {@link IntermediateEncryptingTransport} which was created by a call to
-     * {@link #get(Intent)} with this {@link Intent}.
+     * Cleanup the {@link IntermediateEncryptingTransport} which was created by a call to {@link
+     * #get(Intent)} with this {@link Intent}.
      */
     public void cleanup(Intent intent) {
         Intent transportIntent = TransportClientManager.getRealTransportIntent(intent);
diff --git a/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportTest.java b/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportTest.java
index cc4b0ab..a85b2e4 100644
--- a/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportTest.java
+++ b/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportTest.java
@@ -18,43 +18,71 @@
 
 import static junit.framework.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.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.app.backup.BackupTransport;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.os.ParcelFileDescriptor;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.backup.IBackupTransport;
+import com.android.server.backup.encryption.KeyValueEncrypter;
 import com.android.server.backup.transport.TransportClient;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.io.File;
+
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class IntermediateEncryptingTransportTest {
-    @Mock private IBackupTransport mRealTransport;
-    @Mock private TransportClient mTransportClient;
+    private static final String TEST_PACKAGE_NAME = "test_package";
 
     private IntermediateEncryptingTransport mIntermediateEncryptingTransport;
+    private final PackageInfo mTestPackage = new PackageInfo();
+
+    @Mock private IBackupTransport mRealTransport;
+    @Mock private TransportClient mTransportClient;
+    @Mock private ParcelFileDescriptor mParcelFileDescriptor;
+    @Mock private KeyValueEncrypter mKeyValueEncrypter;
+    @Mock private Context mContext;
+
+    @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
+
+    private File mTempFile;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mIntermediateEncryptingTransport = new IntermediateEncryptingTransport(mTransportClient);
+
+        mIntermediateEncryptingTransport =
+                new IntermediateEncryptingTransport(
+                        mTransportClient, mContext, mKeyValueEncrypter, true);
+        mTestPackage.packageName = TEST_PACKAGE_NAME;
+        mTempFile = mTemporaryFolder.newFile();
+
+        when(mTransportClient.connect(anyString())).thenReturn(mRealTransport);
+        when(mRealTransport.getRestoreData(any())).thenReturn(BackupTransport.TRANSPORT_OK);
     }
 
     @Test
     public void testGetDelegate_callsConnect() throws Exception {
-        when(mTransportClient.connect(anyString())).thenReturn(mRealTransport);
-
         IBackupTransport ret = mIntermediateEncryptingTransport.getDelegate();
 
         assertEquals(mRealTransport, ret);
@@ -74,4 +102,79 @@
         verify(mTransportClient, times(1)).connect(anyString());
         verifyNoMoreInteractions(mTransportClient);
     }
+
+    @Test
+    public void testPerformBackup_shouldEncryptTrue_encryptsDataAndPassesToDelegate()
+            throws Exception {
+        mIntermediateEncryptingTransport =
+                new TestIntermediateTransport(mTransportClient, mContext, mKeyValueEncrypter, true);
+
+        mIntermediateEncryptingTransport.performBackup(mTestPackage, mParcelFileDescriptor, 0);
+
+        verify(mKeyValueEncrypter, times(1))
+                .encryptKeyValueData(eq(TEST_PACKAGE_NAME), eq(mParcelFileDescriptor), any());
+        verify(mRealTransport, times(1)).performBackup(eq(mTestPackage), any(), eq(0));
+    }
+
+    @Test
+    public void testPerformBackup_shouldEncryptFalse_doesntEncryptDataAndPassedToDelegate()
+            throws Exception {
+        mIntermediateEncryptingTransport =
+                new TestIntermediateTransport(
+                        mTransportClient, mContext, mKeyValueEncrypter, false);
+
+        mIntermediateEncryptingTransport.performBackup(mTestPackage, mParcelFileDescriptor, 0);
+
+        verifyZeroInteractions(mKeyValueEncrypter);
+        verify(mRealTransport, times(1))
+                .performBackup(eq(mTestPackage), eq(mParcelFileDescriptor), eq(0));
+    }
+
+    @Test
+    public void testGetRestoreData_shouldEncryptTrue_decryptsDataAndPassesToDelegate()
+            throws Exception {
+        mIntermediateEncryptingTransport =
+                new TestIntermediateTransport(mTransportClient, mContext, mKeyValueEncrypter, true);
+        mIntermediateEncryptingTransport.setNextRestorePackage(TEST_PACKAGE_NAME);
+
+        mIntermediateEncryptingTransport.getRestoreData(mParcelFileDescriptor);
+
+        verify(mKeyValueEncrypter, times(1))
+                .decryptKeyValueData(eq(TEST_PACKAGE_NAME), any(), eq(mParcelFileDescriptor));
+        verify(mRealTransport, times(1)).getRestoreData(any());
+    }
+
+    @Test
+    public void testGetRestoreData_shouldEncryptFalse_doesntDecryptDataAndPassesToDelegate()
+            throws Exception {
+        mIntermediateEncryptingTransport =
+                new TestIntermediateTransport(
+                        mTransportClient, mContext, mKeyValueEncrypter, false);
+        mIntermediateEncryptingTransport.setNextRestorePackage(TEST_PACKAGE_NAME);
+
+        mIntermediateEncryptingTransport.getRestoreData(mParcelFileDescriptor);
+
+        verifyZeroInteractions(mKeyValueEncrypter);
+        verify(mRealTransport, times(1)).getRestoreData(eq(mParcelFileDescriptor));
+    }
+
+    private final class TestIntermediateTransport extends IntermediateEncryptingTransport {
+        TestIntermediateTransport(
+                TransportClient transportClient,
+                Context context,
+                KeyValueEncrypter keyValueEncrypter,
+                boolean shouldEncrypt) {
+            super(transportClient, context, keyValueEncrypter, shouldEncrypt);
+        }
+
+        @Override
+        protected File getBackupTempStorage(String packageName) {
+            return mTempFile;
+        }
+
+        @Override
+        protected File getRestoreTempStorage(String packageName) {
+            return mTempFile;
+        }
+    }
 }
diff --git a/packages/CarSystemUI/res/layout/car_left_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_left_navigation_bar.xml
index 72ec8d8..94f5b96 100644
--- a/packages/CarSystemUI/res/layout/car_left_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_left_navigation_bar.xml
@@ -48,6 +48,18 @@
         />
 
         <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/grid"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            systemui:intent="intent:#Intent;component=com.android.car.home/.AppGridActivity;end"
+            systemui:longIntent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
+            android:src="@drawable/car_ic_apps"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingTop="30dp"
+            android:paddingBottom="30dp"
+        />
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
             android:id="@+id/hvac"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -58,6 +70,7 @@
             android:paddingTop="30dp"
             android:paddingBottom="30dp"
         />
+
     </LinearLayout>
 
     <LinearLayout
@@ -78,6 +91,7 @@
             android:alpha="0.7"
         />
 
+
         <com.android.systemui.statusbar.policy.Clock
             android:id="@+id/clock"
             android:textAppearance="@style/TextAppearance.StatusBar.Clock"
diff --git a/packages/CarSystemUI/res/layout/car_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_navigation_bar.xml
index 897976f..18ae582 100644
--- a/packages/CarSystemUI/res/layout/car_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_navigation_bar.xml
@@ -22,6 +22,8 @@
     android:layout_height="match_parent"
     android:background="@drawable/system_bar_background"
     android:orientation="vertical">
+    <!--The 20dp padding is the difference between the background selected icon size and the ripple
+        that was chosen, thus it's a hack to make it look pretty and not an official margin value-->
     <LinearLayout
         android:id="@id/nav_buttons"
         android:layout_width="match_parent"
@@ -37,7 +39,6 @@
             systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
             systemui:icon="@drawable/car_ic_overview"
             systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
-            systemui:longIntent="intent:#Intent;action=com.google.android.demandspace.START;end"
             systemui:selectedIcon="@drawable/car_ic_overview_selected"
             systemui:useMoreIcon="false"
         />
@@ -108,13 +109,11 @@
             android:layout_height="match_parent"
             android:layout_weight="1"/>
 
-        <!-- Click handling will be initialized in CarNavigationBarView because its
-             id = notifications which is treated special for the opening of the notification panel
-         -->
         <com.android.systemui.statusbar.car.CarNavigationButton
             android:id="@+id/notifications"
             style="@style/NavigationBarButton"
-            android:src="@drawable/car_ic_notification"
+            systemui:icon="@drawable/car_ic_notification"
+            systemui:longIntent="intent:#Intent;component=com.android.car.bugreport/.BugReportActivity;end"
             systemui:selectedIcon="@drawable/car_ic_notification_selected"
             systemui:useMoreIcon="false"
         />
@@ -124,13 +123,13 @@
             android:layout_height="match_parent"
             android:layout_weight="1"/>
 
-        <com.android.systemui.statusbar.car.CarFacetButton
+        <com.android.systemui.statusbar.car.AssitantButton
             android:id="@+id/assist"
             style="@style/NavigationBarButton"
             systemui:icon="@drawable/ic_mic_white"
-            systemui:intent="intent:#Intent;action=com.google.android.demandspace.START;end"
             systemui:useMoreIcon="false"
         />
+
     </LinearLayout>
 
     <LinearLayout
@@ -138,10 +137,11 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_weight="1"
-        android:paddingStart="@*android:dimen/car_keyline_1"
-        android:paddingEnd="@*android:dimen/car_keyline_1"
+        android:paddingStart="@dimen/car_keyline_1"
+        android:paddingEnd="@dimen/car_keyline_1"
         android:gravity="center"
         android:visibility="gone">
+
     </LinearLayout>
 
-</com.android.systemui.statusbar.car.CarNavigationBarView>
+</com.android.systemui.statusbar.car.CarNavigationBarView>
\ No newline at end of file
diff --git a/packages/CarSystemUI/res/layout/car_right_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_right_navigation_bar.xml
index 72ec8d8..d36d1d6 100644
--- a/packages/CarSystemUI/res/layout/car_right_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_right_navigation_bar.xml
@@ -25,6 +25,9 @@
     android:orientation="vertical"
     android:background="@drawable/system_bar_background">
 
+    <!-- phone.NavigationBarView has rot0 and rot90 but we expect the car head unit to have a fixed
+         rotation so skip this level of the hierarchy.
+    -->
     <LinearLayout
         android:layout_height="match_parent"
         android:layout_width="match_parent"
@@ -48,6 +51,18 @@
         />
 
         <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/grid"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            systemui:intent="intent:#Intent;component=com.android.car.home/.AppGridActivity;launchFlags=0x14000000;end"
+            systemui:longIntent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
+            android:src="@drawable/car_ic_apps"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingTop="30dp"
+            android:paddingBottom="30dp"
+        />
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
             android:id="@+id/hvac"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -58,6 +73,7 @@
             android:paddingTop="30dp"
             android:paddingBottom="30dp"
         />
+
     </LinearLayout>
 
     <LinearLayout
@@ -78,6 +94,7 @@
             android:alpha="0.7"
         />
 
+
         <com.android.systemui.statusbar.policy.Clock
             android:id="@+id/clock"
             android:textAppearance="@style/TextAppearance.StatusBar.Clock"
diff --git a/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml b/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml
new file mode 100644
index 0000000..8247211
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/car_top_bar"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/system_bar_background"
+    android:orientation="vertical">
+
+  <RelativeLayout
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:layout_weight="1">
+
+    <FrameLayout
+        android:id="@+id/left_hvac_container"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_alignParentStart="true"
+        >
+
+      <com.android.systemui.statusbar.car.CarNavigationButton
+          android:id="@+id/hvacleft"
+          android:layout_width="match_parent"
+          android:layout_height="match_parent"
+          android:background="@null"
+          systemui:broadcast="true"
+          systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
+          />
+
+      <com.android.systemui.statusbar.hvac.AnimatedTemperatureView
+          android:id="@+id/lefttext"
+          android:layout_width="wrap_content"
+          android:layout_height="match_parent"
+          android:paddingStart="@*android:dimen/car_padding_4"
+          android:paddingEnd="16dp"
+          android:gravity="center_vertical|start"
+          android:minEms="4"
+          android:textAppearance="@style/TextAppearance.CarStatus"
+          systemui:hvacAreaId="49"
+          systemui:hvacMaxText="@string/hvac_max_text"
+          systemui:hvacMaxValue="@dimen/hvac_max_value"
+          systemui:hvacMinText="@string/hvac_min_text"
+          systemui:hvacMinValue="@dimen/hvac_min_value"
+          systemui:hvacPivotOffset="60dp"
+          systemui:hvacPropertyId="358614275"
+          systemui:hvacTempFormat="%.0f\u00B0"
+          />
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/clock_container"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_centerInParent="true">
+      <com.android.systemui.statusbar.car.CarNavigationButton
+          android:id="@+id/qs"
+          android:layout_width="match_parent"
+          android:layout_height="match_parent"
+          android:background="@null"/>
+      <com.android.systemui.statusbar.policy.Clock
+          android:id="@+id/clock"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:layout_gravity="center"
+          android:elevation="5dp"
+          android:singleLine="true"
+          android:textAppearance="@style/TextAppearance.StatusBar.Clock"/>
+    </FrameLayout>
+
+    <LinearLayout
+        android:id="@+id/system_icon_area"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_centerHorizontal="true"
+        android:layout_centerVertical="true"
+        android:layout_toEndOf="@+id/clock_container"
+        android:paddingStart="@*android:dimen/car_padding_1"
+        android:gravity="center_vertical"
+        android:orientation="horizontal"
+        >
+
+      <include
+          layout="@layout/system_icons"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:layout_weight="1"
+          android:paddingStart="4dp"
+          android:gravity="center_vertical"
+          />
+    </LinearLayout>
+
+    <FrameLayout
+        android:id="@+id/right_hvac_container"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_alignParentEnd="true"
+        >
+
+      <com.android.systemui.statusbar.car.CarNavigationButton
+          android:id="@+id/hvacright"
+          android:layout_width="match_parent"
+          android:layout_height="match_parent"
+          android:background="@null"
+          systemui:broadcast="true"
+          systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
+          />
+
+      <com.android.systemui.statusbar.hvac.AnimatedTemperatureView
+          android:id="@+id/righttext"
+          android:layout_width="wrap_content"
+          android:layout_height="match_parent"
+          android:paddingStart="16dp"
+          android:paddingEnd="@*android:dimen/car_padding_4"
+          android:gravity="center_vertical|end"
+          android:minEms="4"
+          android:textAppearance="@style/TextAppearance.CarStatus"
+          systemui:hvacAreaId="68"
+          systemui:hvacMaxText="@string/hvac_max_text"
+          systemui:hvacMaxValue="@dimen/hvac_max_value"
+          systemui:hvacMinText="@string/hvac_min_text"
+          systemui:hvacMinValue="@dimen/hvac_min_value"
+          systemui:hvacPivotOffset="60dp"
+          systemui:hvacPropertyId="358614275"
+          systemui:hvacTempFormat="%.0f\u00B0"
+          />
+    </FrameLayout>
+  </RelativeLayout>
+
+</com.android.systemui.statusbar.car.CarNavigationBarView>
diff --git a/packages/CarSystemUI/res/layout/super_status_bar.xml b/packages/CarSystemUI/res/layout/super_status_bar.xml
index 08d48bf..37cd1d4 100644
--- a/packages/CarSystemUI/res/layout/super_status_bar.xml
+++ b/packages/CarSystemUI/res/layout/super_status_bar.xml
@@ -69,10 +69,10 @@
             android:visibility="gone"
         />
 
-        <include layout="@layout/car_top_navigation_bar"
+        <FrameLayout
+            android:id="@+id/car_top_navigation_bar_container"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-        />
+            android:layout_height="wrap_content"/>
     </LinearLayout>
 
     <include layout="@layout/brightness_mirror"/>
diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml
index fb422af..e2da91b 100644
--- a/packages/CarSystemUI/res/values/dimens.xml
+++ b/packages/CarSystemUI/res/values/dimens.xml
@@ -120,4 +120,73 @@
     <dimen name="notification_shade_handle_bar_margin_bottom">10dp</dimen>
     <dimen name="notification_shade_list_padding_bottom">50dp</dimen>
 
+    <!-- The alpha for the scrim behind the notification shade. This value is 1 so that the
+     scrim has no transparency. -->
+    <item name="scrim_behind_alpha" format="float" type="dimen">1.0</item>
+
+    <!-- The width of panel holding the notification card. -->
+    <dimen name="notification_panel_width">522dp</dimen>
+
+    <!-- The width of the quick settings panel. -1 for match_parent. -->
+    <dimen name="qs_panel_width">-1px</dimen>
+
+    <!-- Height of a small notification in the status bar-->
+    <dimen name="notification_min_height">192dp</dimen>
+
+    <!-- Height of a small notification in the status bar which was used before android N -->
+    <dimen name="notification_min_height_legacy">192dp</dimen>
+
+    <!-- Height of a large notification in the status bar -->
+    <dimen name="notification_max_height">400dp</dimen>
+
+    <!-- Height of a heads up notification in the status bar for legacy custom views -->
+    <dimen name="notification_max_heads_up_height_legacy">400dp</dimen>
+
+    <!-- Height of a heads up notification in the status bar -->
+    <dimen name="notification_max_heads_up_height">400dp</dimen>
+
+    <!-- Height of the status bar header bar -->
+    <dimen name="status_bar_header_height">54dp</dimen>
+
+    <!-- The height of the divider between the individual notifications. -->
+    <dimen name="notification_divider_height">16dp</dimen>
+
+    <!-- The height of the divider between the individual notifications when the notification
+         wants it to be increased. This value is the same as notification_divider_height so that
+         the spacing between all notifications will always be the same. -->
+    <dimen name="notification_divider_height_increased">@dimen/notification_divider_height</dimen>
+
+    <!-- The alpha of the dividing line between child notifications of a notification group. -->
+    <item name="notification_divider_alpha" format="float" type="dimen">1.0</item>
+
+    <!-- The width of each individual notification card. -->
+    <dimen name="notification_child_width">522dp</dimen>
+
+    <!-- The top margin of the notification panel. -->
+    <dimen name="notification_panel_margin_top">32dp</dimen>
+
+    <!-- The bottom margin of the panel that holds the list of notifications. -->
+    <dimen name="notification_panel_margin_bottom">@dimen/notification_divider_height</dimen>
+
+    <!-- The corner radius of the shadow behind the notification. -->
+    <dimen name="notification_shadow_radius">16dp</dimen>
+
+    <!-- The amount of space below the notification list. This value is 0 so the list scrolls
+         all the way to the bottom. -->
+    <dimen name="close_handle_underlap">0dp</dimen>
+
+    <!-- The height of the divider between the individual notifications in a notification group. -->
+    <dimen name="notification_children_container_divider_height">1dp</dimen>
+
+    <!-- The height of the header for a container containing child notifications. -->
+    <dimen name="notification_children_container_header_height">76dp</dimen>
+
+    <!-- The top margin for the notification children container in its non-expanded form. This
+         value is smaller than notification_children_container_header_height to bring the first
+         child closer so there is less wasted space. -->
+    <dimen name="notification_children_container_margin_top">68dp</dimen>
+
+    <!-- The height of the quick settings footer that holds the user switcher, settings icon,
+         etc. in the car setting.-->
+    <dimen name="qs_footer_height">74dp</dimen>
 </resources>
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index a585727..1eeaa7c 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -87,6 +87,7 @@
 import com.android.systemui.qs.car.CarQSFragment;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.NavigationBarController;
 import com.android.systemui.statusbar.NotificationListener;
@@ -102,7 +103,7 @@
 import com.android.systemui.statusbar.car.hvac.TemperatureView;
 import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotifPipelineInitializer;
+import com.android.systemui.statusbar.notification.NewNotifPipeline;
 import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
@@ -113,6 +114,7 @@
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.phone.AutoHideController;
 import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
+import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.LightBarController;
@@ -139,6 +141,8 @@
 import javax.inject.Inject;
 import javax.inject.Named;
 
+import dagger.Lazy;
+
 /**
  * A status bar (and navigation bar) tailored for the automotive use case.
  */
@@ -162,9 +166,11 @@
     private BatteryMeterView mBatteryMeterView;
     private Drawable mNotificationPanelBackground;
 
+    private ViewGroup mTopNavigationBarContainer;
     private ViewGroup mNavigationBarWindow;
     private ViewGroup mLeftNavigationBarWindow;
     private ViewGroup mRightNavigationBarWindow;
+    private CarNavigationBarView mTopNavigationBarView;
     private CarNavigationBarView mNavigationBarView;
     private CarNavigationBarView mLeftNavigationBarView;
     private CarNavigationBarView mRightNavigationBarView;
@@ -176,7 +182,7 @@
     private CarFacetButtonController mCarFacetButtonController;
     private ActivityManagerWrapper mActivityManagerWrapper;
     private DeviceProvisionedController mDeviceProvisionedController;
-    private boolean mDeviceIsProvisioned = true;
+    private boolean mDeviceIsSetUpForUser = true;
     private HvacController mHvacController;
     private DrivingStateHelper mDrivingStateHelper;
     private PowerManagerHelper mPowerManagerHelper;
@@ -197,6 +203,9 @@
     private boolean mNotificationListAtBottom;
     // Was the notification list at the bottom when the user first touched the screen
     private boolean mNotificationListAtBottomAtTimeOfTouch;
+    // To be attached to the top navigation bar (i.e. status bar) to pull down the notification
+    // panel.
+    private View.OnTouchListener mTopNavBarNotificationTouchListener;
     // To be attached to the navigation bars such that they can close the notification panel if
     // it's open.
     private View.OnTouchListener mNavBarNotificationTouchListener;
@@ -246,6 +255,7 @@
     @Inject
     public CarStatusBar(
             Context context,
+            FeatureFlags featureFlags,
             LightBarController lightBarController,
             AutoHideController autoHideController,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
@@ -260,7 +270,7 @@
             DynamicPrivacyController dynamicPrivacyController,
             BypassHeadsUpNotifier bypassHeadsUpNotifier,
             @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
-            NotifPipelineInitializer notifPipelineInitializer,
+            Lazy<NewNotifPipeline> newNotifPipeline,
             FalsingManager falsingManager,
             BroadcastDispatcher broadcastDispatcher,
             RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
@@ -299,9 +309,11 @@
             ConfigurationController configurationController,
             StatusBarWindowController statusBarWindowController,
             StatusBarWindowViewController.Builder statusBarWindowViewControllerBuild,
-            NotifLog notifLog) {
+            NotifLog notifLog,
+            DozeParameters dozeParameters) {
         super(
                 context,
+                featureFlags,
                 lightBarController,
                 autoHideController,
                 keyguardUpdateMonitor,
@@ -316,7 +328,7 @@
                 dynamicPrivacyController,
                 bypassHeadsUpNotifier,
                 allowNotificationLongPress,
-                notifPipelineInitializer,
+                newNotifPipeline,
                 falsingManager,
                 broadcastDispatcher,
                 remoteInputQuickSettingsDisabler,
@@ -355,7 +367,8 @@
                 configurationController,
                 statusBarWindowController,
                 statusBarWindowViewControllerBuild,
-                notifLog);
+                notifLog,
+                dozeParameters);
         mNavigationBarController = navigationBarController;
     }
 
@@ -364,7 +377,7 @@
         // get the provisioned state before calling the parent class since it's that flow that
         // builds the nav bar
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
-        mDeviceIsProvisioned = mDeviceProvisionedController.isDeviceProvisioned();
+        mDeviceIsSetUpForUser = mDeviceProvisionedController.isCurrentUserSetup();
 
         // Keyboard related setup, before nav bars are created.
         mHideNavBarForKeyboard = mContext.getResources().getBoolean(
@@ -376,6 +389,10 @@
         mScreenLifecycle = Dependency.get(ScreenLifecycle.class);
         mScreenLifecycle.addObserver(mScreenObserver);
 
+        // Need to initialize HVAC controller before calling super.start - before system bars are
+        // created.
+        mHvacController = new HvacController(mContext);
+
         super.start();
         mTaskStackListener = new TaskStackListenerImpl();
         mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
@@ -394,25 +411,18 @@
 
         mHvacController.connectToCarService();
 
-        CarSystemUIFactory factory = SystemUIFactory.getInstance();
-        if (!mDeviceIsProvisioned) {
-            mDeviceProvisionedController.addCallback(
-                    new DeviceProvisionedController.DeviceProvisionedListener() {
-                        @Override
-                        public void onDeviceProvisionedChanged() {
-                            mHandler.post(() -> {
-                                // on initial boot we are getting a call even though the value
-                                // is the same so we are confirming the reset is needed
-                                boolean deviceProvisioned =
-                                        mDeviceProvisionedController.isDeviceProvisioned();
-                                if (mDeviceIsProvisioned != deviceProvisioned) {
-                                    mDeviceIsProvisioned = deviceProvisioned;
-                                    restartNavBars();
-                                }
-                            });
-                        }
-                    });
-        }
+        mDeviceProvisionedController.addCallback(
+                new DeviceProvisionedController.DeviceProvisionedListener() {
+                    @Override
+                    public void onUserSetupChanged() {
+                        mHandler.post(() -> restartNavBarsIfNecessary());
+                    }
+
+                    @Override
+                    public void onUserSwitched() {
+                        mHandler.post(() -> restartNavBarsIfNecessary());
+                    }
+                });
 
         // Register a listener for driving state changes.
         mDrivingStateHelper = new DrivingStateHelper(mContext, this::onDrivingStateChanged);
@@ -424,6 +434,14 @@
         mSwitchToGuestTimer = new SwitchToGuestTimer(mContext);
     }
 
+    private void restartNavBarsIfNecessary() {
+        boolean currentUserSetup = mDeviceProvisionedController.isCurrentUserSetup();
+        if (mDeviceIsSetUpForUser != currentUserSetup) {
+            mDeviceIsSetUpForUser = currentUserSetup;
+            restartNavBars();
+        }
+    }
+
     /**
      * Remove all content from navbars and rebuild them. Used to allow for different nav bars
      * before and after the device is provisioned. . Also for change of density and font size.
@@ -432,8 +450,8 @@
         // remove and reattach all hvac components such that we don't keep a reference to unused
         // ui elements
         mHvacController.removeAllComponents();
-        addTemperatureViewToController(mStatusBarWindow);
         mCarFacetButtonController.removeAll();
+
         if (mNavigationBarWindow != null) {
             mNavigationBarWindow.removeAllViews();
             mNavigationBarView = null;
@@ -527,7 +545,6 @@
     @Override
     protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
         super.makeStatusBarView(result);
-        mHvacController = new HvacController(mContext);
 
         CarSystemUIFactory factory = SystemUIFactory.getInstance();
         mCarFacetButtonController = factory.getCarDependencyComponent()
@@ -552,7 +569,8 @@
      * touch listeners needed for opening and closing the notification panel
      */
     private void connectNotificationsUI() {
-        // Attached to the status bar to detect pull down of the notification shade.
+        // Attached to the top navigation bar (i.e. status bar) to detect pull down of the
+        // notification shade.
         GestureDetector openGestureDetector = new GestureDetector(mContext,
                 new OpenNotificationGestureListener() {
                     @Override
@@ -585,6 +603,18 @@
         GestureDetector handleBarCloseNotificationGestureDetector = new GestureDetector(mContext,
                 new HandleBarCloseNotificationGestureListener());
 
+        mTopNavBarNotificationTouchListener = (v, event) -> {
+            if (!mDeviceIsSetUpForUser) {
+                return true;
+            }
+            boolean consumed = openGestureDetector.onTouchEvent(event);
+            if (consumed) {
+                return true;
+            }
+            maybeCompleteAnimation(event);
+            return true;
+        };
+
         mNavBarNotificationTouchListener =
                 (v, event) -> {
                     boolean consumed = navBarCloseNotificationGestureDetector.onTouchEvent(event);
@@ -595,21 +625,6 @@
                     return true;
                 };
 
-        // The following are the ui elements that the user would call the status bar.
-        // This will set the status bar so it they can make call backs.
-        CarNavigationBarView topBar = mStatusBarWindow.findViewById(R.id.car_top_bar);
-        topBar.setStatusBar(this);
-        topBar.setStatusBarWindowTouchListener((v1, event1) -> {
-
-                    boolean consumed = openGestureDetector.onTouchEvent(event1);
-                    if (consumed) {
-                        return true;
-                    }
-                    maybeCompleteAnimation(event1);
-                    return true;
-                }
-        );
-
         mNotificationClickHandlerFactory = new NotificationClickHandlerFactory(mBarService);
         mNotificationClickHandlerFactory.registerClickListener((launchResult, alertEntry) -> {
             if (launchResult == ActivityManager.START_TASK_TO_FRONT
@@ -916,23 +931,30 @@
     }
 
     private void buildNavBarContent() {
+        // Always build top bar.
+        buildTopBar((mDeviceIsSetUpForUser) ? R.layout.car_top_navigation_bar :
+                R.layout.car_top_navigation_bar_unprovisioned);
+
         if (mShowBottom) {
-            buildBottomBar((mDeviceIsProvisioned) ? R.layout.car_navigation_bar :
+            buildBottomBar((mDeviceIsSetUpForUser) ? R.layout.car_navigation_bar :
                     R.layout.car_navigation_bar_unprovisioned);
         }
 
         if (mShowLeft) {
-            buildLeft((mDeviceIsProvisioned) ? R.layout.car_left_navigation_bar :
+            buildLeft((mDeviceIsSetUpForUser) ? R.layout.car_left_navigation_bar :
                     R.layout.car_left_navigation_bar_unprovisioned);
         }
 
         if (mShowRight) {
-            buildRight((mDeviceIsProvisioned) ? R.layout.car_right_navigation_bar :
+            buildRight((mDeviceIsSetUpForUser) ? R.layout.car_right_navigation_bar :
                     R.layout.car_right_navigation_bar_unprovisioned);
         }
     }
 
     private void buildNavBarWindows() {
+        mTopNavigationBarContainer = mStatusBarWindow
+            .findViewById(R.id.car_top_navigation_bar_container);
+
         if (mShowBottom) {
             mNavigationBarWindow = (ViewGroup) View.inflate(mContext,
                     R.layout.navigation_bar_window, null);
@@ -965,15 +987,25 @@
         }
 
         boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0;
-        if (!isKeyboardVisible) {
-            attachBottomNavBarWindow();
-        } else {
-            detachBottomNavBarWindow();
-        }
+        showBottomNavBarWindow(isKeyboardVisible);
     }
 
     private void attachNavBarWindows() {
-        attachBottomNavBarWindow();
+        if (mShowBottom && !mBottomNavBarVisible) {
+            mBottomNavBarVisible = true;
+
+            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                    LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
+                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
+                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                            | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                            | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                            | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+                    PixelFormat.TRANSLUCENT);
+            lp.setTitle("CarNavigationBar");
+            lp.windowAnimations = 0;
+            mWindowManager.addView(mNavigationBarWindow, lp);
+        }
 
         if (mShowLeft) {
             int width = mContext.getResources().getDimensionPixelSize(
@@ -1011,47 +1043,32 @@
         }
     }
 
-    /**
-     * Attaches the bottom nav bar window. Can be extended to modify the specific behavior of
-     * attaching the bottom nav bar.
-     */
-    protected void attachBottomNavBarWindow() {
+    private void showBottomNavBarWindow(boolean isKeyboardVisible) {
         if (!mShowBottom) {
             return;
         }
 
-        if (mBottomNavBarVisible) {
+        // If keyboard is visible and bottom nav bar not visible, this is the correct state, so do
+        // nothing. Same with if keyboard is not visible and bottom nav bar is visible.
+        if (isKeyboardVisible ^ mBottomNavBarVisible) {
             return;
         }
-        mBottomNavBarVisible = true;
 
-        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
-                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
-                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
-                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
-                PixelFormat.TRANSLUCENT);
-        lp.setTitle("CarNavigationBar");
-        lp.windowAnimations = 0;
-        mWindowManager.addView(mNavigationBarWindow, lp);
+        mNavigationBarWindow.setVisibility(isKeyboardVisible ? View.GONE : View.VISIBLE);
+        mBottomNavBarVisible = !isKeyboardVisible;
     }
 
-    /**
-     * Detaches the bottom nav bar window. Can be extended to modify the specific behavior of
-     * detaching the bottom nav bar.
-     */
-    protected void detachBottomNavBarWindow() {
-        if (!mShowBottom) {
-            return;
+    private void buildTopBar(int layout) {
+        mTopNavigationBarContainer.removeAllViews();
+        View.inflate(mContext, layout, mTopNavigationBarContainer);
+        mTopNavigationBarView = (CarNavigationBarView) mTopNavigationBarContainer.getChildAt(0);
+        if (mTopNavigationBarView == null) {
+            Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_top_navigation_bar");
+            throw new RuntimeException("Unable to build top nav bar due to missing layout");
         }
-
-        if (!mBottomNavBarVisible) {
-            return;
-        }
-        mBottomNavBarVisible = false;
-        mWindowManager.removeView(mNavigationBarWindow);
+        mTopNavigationBarView.setStatusBar(this);
+        addTemperatureViewToController(mTopNavigationBarView);
+        mTopNavigationBarView.setStatusBarWindowTouchListener(mTopNavBarNotificationTouchListener);
     }
 
     private void buildBottomBar(int layout) {
@@ -1062,7 +1079,7 @@
         mNavigationBarView = (CarNavigationBarView) mNavigationBarWindow.getChildAt(0);
         if (mNavigationBarView == null) {
             Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
-            throw new RuntimeException("Unable to build botom nav bar due to missing layout");
+            throw new RuntimeException("Unable to build bottom nav bar due to missing layout");
         }
         mNavigationBarView.setStatusBar(this);
         addTemperatureViewToController(mNavigationBarView);
@@ -1073,7 +1090,7 @@
         View.inflate(mContext, layout, mLeftNavigationBarWindow);
         mLeftNavigationBarView = (CarNavigationBarView) mLeftNavigationBarWindow.getChildAt(0);
         if (mLeftNavigationBarView == null) {
-            Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
+            Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_left_navigation_bar");
             throw new RuntimeException("Unable to build left nav bar due to missing layout");
         }
         mLeftNavigationBarView.setStatusBar(this);
@@ -1086,7 +1103,7 @@
         View.inflate(mContext, layout, mRightNavigationBarWindow);
         mRightNavigationBarView = (CarNavigationBarView) mRightNavigationBarWindow.getChildAt(0);
         if (mRightNavigationBarView == null) {
-            Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
+            Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_right_navigation_bar");
             throw new RuntimeException("Unable to build right nav bar due to missing layout");
         }
         mRightNavigationBarView.setStatusBar(this);
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 886162f..beea1ac 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -19,6 +19,7 @@
 import static android.content.DialogInterface.BUTTON_NEGATIVE;
 import static android.content.DialogInterface.BUTTON_POSITIVE;
 
+import android.app.ActivityManager;
 import android.app.AlertDialog;
 import android.app.AlertDialog.Builder;
 import android.app.Dialog;
@@ -34,6 +35,7 @@
 import android.graphics.Rect;
 import android.os.AsyncTask;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -52,6 +54,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * Displays a GridLayout with icons for the users in the system to allow switching between users.
@@ -61,6 +65,7 @@
     private UserSelectionListener mUserSelectionListener;
     private UserAdapter mAdapter;
     private CarUserManagerHelper mCarUserManagerHelper;
+    private UserManager mUserManager;
     private Context mContext;
 
     private final BroadcastReceiver mUserUpdateReceiver = new BroadcastReceiver() {
@@ -74,8 +79,9 @@
         super(context, attrs);
         mContext = context;
         mCarUserManagerHelper = new CarUserManagerHelper(mContext);
+        mUserManager = UserManager.get(mContext);
 
-        addItemDecoration(new ItemSpacingDecoration(context.getResources().getDimensionPixelSize(
+        addItemDecoration(new ItemSpacingDecoration(mContext.getResources().getDimensionPixelSize(
                 R.dimen.car_user_switcher_vertical_spacing_between_users)));
     }
 
@@ -103,12 +109,23 @@
      * @return the adapter
      */
     public void buildAdapter() {
-        List<UserRecord> userRecords = createUserRecords(mCarUserManagerHelper
-                .getAllUsers());
+        List<UserRecord> userRecords = createUserRecords(getAllUsers());
         mAdapter = new UserAdapter(mContext, userRecords);
         super.setAdapter(mAdapter);
     }
 
+    private List<UserInfo> getAllUsers() {
+        Stream<UserInfo> userListStream =
+                mUserManager.getUsers(/* excludeDying= */ true).stream();
+
+        if (UserManager.isHeadlessSystemUserMode()) {
+            userListStream =
+                    userListStream.filter(userInfo -> userInfo.id != UserHandle.USER_SYSTEM);
+        }
+        userListStream = userListStream.filter(userInfo -> userInfo.supportsSwitchToByUser());
+        return userListStream.collect(Collectors.toList());
+    }
+
     private List<UserRecord> createUserRecords(List<UserInfo> userInfoList) {
         List<UserRecord> userRecords = new ArrayList<>();
 
@@ -124,8 +141,7 @@
                 continue;
             }
 
-            boolean isForeground =
-                    mCarUserManagerHelper.getCurrentForegroundUserId() == userInfo.id;
+            boolean isForeground = ActivityManager.getCurrentUser() == userInfo.id;
             UserRecord record = new UserRecord(userInfo, false /* isStartGuestSession */,
                     false /* isAddUser */, isForeground);
             userRecords.add(record);
@@ -143,7 +159,7 @@
     }
 
     private UserRecord createForegroundUserRecord() {
-        return new UserRecord(mCarUserManagerHelper.getCurrentForegroundUserInfo(),
+        return new UserRecord(mUserManager.getUserInfo(ActivityManager.getCurrentUser()),
                 false /* isStartGuestSession */, false /* isAddUser */, true /* isForeground */);
     }
 
@@ -173,7 +189,7 @@
 
     private void onUsersUpdate() {
         mAdapter.clearUsers();
-        mAdapter.updateUsers(createUserRecords(mCarUserManagerHelper.getAllUsers()));
+        mAdapter.updateUsers(createUserRecords(getAllUsers()));
         mAdapter.notifyDataSetChanged();
     }
 
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java
index ead1de2..88d641e 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java
@@ -47,6 +47,7 @@
 public class OngoingPrivacyChip extends LinearLayout implements View.OnClickListener {
 
     private Context mContext;
+    private Handler mHandler;
 
     private LinearLayout mIconsContainer;
     private List<PrivacyItem> mPrivacyItems;
@@ -88,6 +89,7 @@
 
     private void init(Context context) {
         mContext = context;
+        mHandler = new Handler(Looper.getMainLooper());
         mPrivacyItems = new ArrayList<>();
         sAppOpsController = Dependency.get(AppOpsController.class);
         mUserManager = mContext.getSystemService(UserManager.class);
@@ -131,8 +133,7 @@
     @Override
     public void onClick(View v) {
         updatePrivacyList();
-        Handler mUiHandler = new Handler(Looper.getMainLooper());
-        mUiHandler.post(() -> {
+        mHandler.post(() -> {
             mActivityStarter.postStartActivityDismissingKeyguard(
                     new Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE), 0);
         });
@@ -152,21 +153,17 @@
     }
 
     private void updatePrivacyList() {
-        mPrivacyItems = mCurrentUserIds.stream()
+        List<PrivacyItem> privacyItems = mCurrentUserIds.stream()
                 .flatMap(item -> sAppOpsController.getActiveAppOpsForUser(item).stream())
                 .filter(Objects::nonNull)
                 .map(item -> toPrivacyItem(item))
                 .filter(Objects::nonNull)
                 .collect(Collectors.toList());
-        mPrivacyDialogBuilder = new PrivacyDialogBuilder(mContext, mPrivacyItems);
-
-        Handler refresh = new Handler(Looper.getMainLooper());
-        refresh.post(new Runnable() {
-            @Override
-            public void run() {
-                updateView();
-            }
-        });
+        if (!privacyItems.equals(mPrivacyItems)) {
+            mPrivacyItems = privacyItems;
+            mPrivacyDialogBuilder = new PrivacyDialogBuilder(mContext, mPrivacyItems);
+            mHandler.post(this::updateView);
+        }
     }
 
     private PrivacyItem toPrivacyItem(AppOpItem appOpItem) {
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
index 5ec7a77..a5d3bf7 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
@@ -16,28 +16,31 @@
 
 package com.android.systemui.statusbar.car.privacy;
 
-import android.car.userlib.CarUserManagerHelper;
+import android.app.ActivityManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
 import android.util.Log;
 
+import java.util.Objects;
+
 /**
  * Class to hold the data for the applications that are using the AppOps permissions.
  */
 public class PrivacyApplication {
     private static final String TAG = "PrivacyApplication";
 
+    private String mPackageName;
     private Drawable mIcon;
     private String mApplicationName;
 
     public PrivacyApplication(String packageName, Context context) {
+        mPackageName = packageName;
         try {
-            CarUserManagerHelper carUserManagerHelper = new CarUserManagerHelper(context);
             ApplicationInfo app = context.getPackageManager()
                     .getApplicationInfoAsUser(packageName, 0,
-                            carUserManagerHelper.getCurrentForegroundUserId());
+                            ActivityManager.getCurrentUser());
             mIcon = context.getPackageManager().getApplicationIcon(app);
             mApplicationName = context.getPackageManager().getApplicationLabel(app).toString();
         } catch (PackageManager.NameNotFoundException e) {
@@ -59,4 +62,17 @@
     public String getApplicationName() {
         return mApplicationName;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        PrivacyApplication that = (PrivacyApplication) o;
+        return mPackageName.equals(that.mPackageName);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mPackageName);
+    }
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java
index fca1373..d3e123e 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.car.privacy;
 
+import java.util.Objects;
+
 /**
  * Class for holding the data of each privacy item displayed in {@link OngoingPrivacyDialog}
  */
@@ -43,4 +45,18 @@
     public PrivacyType getPrivacyType() {
         return mPrivacyType;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        PrivacyItem that = (PrivacyItem) o;
+        return mPrivacyType == that.mPrivacyType
+                && mPrivacyApplication.equals(that.mPrivacyApplication);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mPrivacyType, mPrivacyApplication);
+    }
 }
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index 81c5bcd..642dc82 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -35,7 +35,6 @@
 import android.net.http.SslError;
 import android.os.Bundle;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -477,11 +476,11 @@
     }
 
     private static void logd(String s) {
-        Rlog.d(TAG, s);
+        Log.d(TAG, s);
     }
 
     private static void loge(String s) {
-        Rlog.d(TAG, s);
+        Log.d(TAG, s);
     }
 
 }
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
index 02c61d7..46b1d5f 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
@@ -19,7 +19,6 @@
 import android.content.Intent;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -27,7 +26,6 @@
 import com.android.internal.util.ArrayUtils;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -44,7 +42,7 @@
     private static final String INTER_GROUP_DELIMITER = "\\s*:\\s*";
 
     private static final String TAG = CustomConfigLoader.class.getSimpleName();
-    private static final boolean VDBG = Rlog.isLoggable(TAG, Log.VERBOSE);
+    private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
 
     /**
      * loads and parses the carrier config, return a list of carrier action for the given signal
@@ -70,7 +68,7 @@
         // return an empty list if no match found
         List<Integer> actionList = new ArrayList<>();
         if (carrierConfigManager == null) {
-            Rlog.e(TAG, "load carrier config failure with carrier config manager uninitialized");
+            Log.e(TAG, "load carrier config failure with carrier config manager uninitialized");
             return actionList;
         }
         PersistableBundle b = carrierConfigManager.getConfig();
@@ -101,8 +99,8 @@
                             .EXTRA_DEFAULT_NETWORK_AVAILABLE_KEY, false));
                     break;
                 default:
-                    Rlog.e(TAG, "load carrier config failure with un-configured key: " +
-                            intent.getAction());
+                    Log.e(TAG, "load carrier config failure with un-configured key: "
+                            + intent.getAction());
                     break;
             }
             if (!ArrayUtils.isEmpty(configs)) {
@@ -111,12 +109,12 @@
                     matchConfig(config, arg1, arg2, actionList);
                     if (!actionList.isEmpty()) {
                         // return the first match
-                        if (VDBG) Rlog.d(TAG, "found match action list: " + actionList.toString());
+                        if (VDBG) Log.d(TAG, "found match action list: " + actionList.toString());
                         return actionList;
                     }
                 }
             }
-            Rlog.d(TAG, "no matching entry for signal: " + intent.getAction() + "arg1: " + arg1
+            Log.d(TAG, "no matching entry for signal: " + intent.getAction() + "arg1: " + arg1
                     + "arg2: " + arg2);
         }
         return actionList;
@@ -166,7 +164,7 @@
                 try {
                     actionList.add(Integer.parseInt(idx));
                 } catch (NumberFormatException e) {
-                    Rlog.e(TAG, "NumberFormatException(string: " + idx + " config:" + config + "): "
+                    Log.e(TAG, "NumberFormatException(string: " + idx + " config:" + config + "): "
                             + e);
                 }
             }
diff --git a/packages/EncryptedLocalTransport/Android.bp b/packages/EncryptedLocalTransport/Android.bp
new file mode 100644
index 0000000..dd30ad1
--- /dev/null
+++ b/packages/EncryptedLocalTransport/Android.bp
@@ -0,0 +1,27 @@
+//
+// 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.
+//
+
+android_app {
+    name: "EncryptedLocalTransport",
+    srcs: ["src/**/*.java"],
+    optimize: {
+        proguard_flags_files: ["proguard.flags"],
+    },
+    static_libs: ["LocalTransport"],
+    platform_apis: true,
+    certificate: "platform",
+    privileged: true,
+}
diff --git a/packages/EncryptedLocalTransport/AndroidManifest.xml b/packages/EncryptedLocalTransport/AndroidManifest.xml
new file mode 100644
index 0000000..dc3617f
--- /dev/null
+++ b/packages/EncryptedLocalTransport/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2019 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.android.encryptedlocaltransport"
+      android:sharedUserId="android.uid.system" >
+
+
+    <application android:allowBackup="false" >
+        <!-- This service does not need to be exported because it shares uid with the system server
+        which is the only client. -->
+        <service android:name=".EncryptedLocalTransportService"
+                 android:permission="android.permission.CONFIRM_FULL_BACKUP"
+                 android:exported="false">
+            <intent-filter>
+                <action android:name="android.backup.TRANSPORT_HOST" />
+            </intent-filter>
+        </service>
+
+    </application>
+</manifest>
diff --git a/packages/EncryptedLocalTransport/proguard.flags b/packages/EncryptedLocalTransport/proguard.flags
new file mode 100644
index 0000000..e4ce3c5
--- /dev/null
+++ b/packages/EncryptedLocalTransport/proguard.flags
@@ -0,0 +1,2 @@
+-keep class com.android.localTransport.EncryptedLocalTransport
+-keep class com.android.localTransport.EncryptedLocalTransportService
diff --git a/packages/EncryptedLocalTransport/src/com/android/encryptedlocaltransport/EncryptedLocalTransport.java b/packages/EncryptedLocalTransport/src/com/android/encryptedlocaltransport/EncryptedLocalTransport.java
new file mode 100644
index 0000000..3dd453e
--- /dev/null
+++ b/packages/EncryptedLocalTransport/src/com/android/encryptedlocaltransport/EncryptedLocalTransport.java
@@ -0,0 +1,109 @@
+/*
+ * 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.encryptedlocaltransport;
+
+import android.app.backup.BackupTransport;
+import android.app.backup.RestoreDescription;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.os.ParcelFileDescriptor;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructStat;
+import android.util.Log;
+
+import com.android.localtransport.LocalTransport;
+import com.android.localtransport.LocalTransportParameters;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+
+public class EncryptedLocalTransport extends LocalTransport {
+    private static final String TAG = "EncryptedLocalTransport";
+    private static final int BACKUP_BUFFER_SIZE = 32 * 1024; // 32 KB.
+
+    public EncryptedLocalTransport(Context context,
+            LocalTransportParameters parameters) {
+        super(context, parameters);
+    }
+
+    @Override
+    public int performBackup(
+            PackageInfo packageInfo, ParcelFileDescriptor data, int flags) {
+        File packageFile;
+        try {
+            StructStat stat = Os.fstat(data.getFileDescriptor());
+            if (stat.st_size > KEY_VALUE_BACKUP_SIZE_QUOTA) {
+                Log.w(TAG, "New datastore size " + stat.st_size
+                        + " exceeds quota " + KEY_VALUE_BACKUP_SIZE_QUOTA);
+                return TRANSPORT_QUOTA_EXCEEDED;
+            }
+        } catch (ErrnoException e) {
+            Log.w(TAG, "Failed to stat the backup input file: ", e);
+            return BackupTransport.TRANSPORT_ERROR;
+        }
+
+        clearBackupData(packageInfo);
+
+        try (InputStream in = new FileInputStream(data.getFileDescriptor())) {
+            packageFile = new File(mCurrentSetIncrementalDir, packageInfo.packageName);
+            Files.copy(in, packageFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+        } catch (IOException e) {
+            Log.w(TAG, "Failed to save backup data to file: ", e);
+            return BackupTransport.TRANSPORT_ERROR;
+        }
+
+        return TRANSPORT_OK;
+    }
+
+    @Override
+    public int getRestoreData(ParcelFileDescriptor outFd) {
+        if (mRestorePackages == null) {
+            throw new IllegalStateException("startRestore not called");
+        }
+        if (mRestorePackage < 0) {
+            throw new IllegalStateException("nextRestorePackage not called");
+        }
+        if (mRestoreType != RestoreDescription.TYPE_KEY_VALUE) {
+            throw new IllegalStateException("getRestoreData(fd) for non-key/value dataset");
+        }
+
+        try(OutputStream out = new FileOutputStream(outFd.getFileDescriptor())) {
+            File packageFile = new File(mRestoreSetIncrementalDir,
+                    mRestorePackages[mRestorePackage].packageName);
+            Files.copy(packageFile.toPath(), out);
+        } catch (IOException e) {
+            Log.d(TAG, "Failed to transfer restore data: " + e);
+            return BackupTransport.TRANSPORT_ERROR;
+        }
+
+        return BackupTransport.TRANSPORT_OK;
+    }
+
+    @Override
+    protected boolean hasRestoreDataForPackage(String packageName) {
+        File contents = (new File(mRestoreSetIncrementalDir, packageName));
+        return contents.exists() && contents.length() != 0;
+
+    }
+}
diff --git a/packages/EncryptedLocalTransport/src/com/android/encryptedlocaltransport/EncryptedLocalTransportService.java b/packages/EncryptedLocalTransport/src/com/android/encryptedlocaltransport/EncryptedLocalTransportService.java
new file mode 100644
index 0000000..952f90d
--- /dev/null
+++ b/packages/EncryptedLocalTransport/src/com/android/encryptedlocaltransport/EncryptedLocalTransportService.java
@@ -0,0 +1,47 @@
+/*
+ * 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.encryptedlocaltransport;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+import com.android.localtransport.LocalTransportParameters;
+
+public class EncryptedLocalTransportService extends Service {
+    private static EncryptedLocalTransport sTransport = null;
+
+    @Override
+    public void onCreate() {
+        if (sTransport == null) {
+            LocalTransportParameters parameters =
+                    new LocalTransportParameters(getMainThreadHandler(), getContentResolver());
+            sTransport = new EncryptedLocalTransport(this, parameters);
+        }
+        sTransport.getParameters().start();
+    }
+
+    @Override
+    public void onDestroy() {
+        sTransport.getParameters().stop();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return sTransport.getBinder();
+    }
+}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 1b27b52..48d34ae 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -16,6 +16,7 @@
 
 package com.android.externalstorage;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.usage.StorageStatsManager;
 import android.content.ContentResolver;
@@ -298,6 +299,53 @@
         return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
     }
 
+    /**
+     * Check that the directory is the root of storage or blocked file from tree.
+     *
+     * @param docId the docId of the directory to be checked
+     * @return true, should be blocked from tree. Otherwise, false.
+     */
+    @Override
+    protected boolean shouldBlockFromTree(@NonNull String docId) {
+        try {
+            final File dir = getFileForDocId(docId, true /* visible */).getCanonicalFile();
+            if (!dir.isDirectory()) {
+                return false;
+            }
+
+            final String path = dir.getAbsolutePath();
+
+            // Block Download folder from tree
+            if (MediaStore.Downloads.isDownloadDir(path)) {
+                return true;
+            }
+
+            final ArrayMap<String, RootInfo> roots = new ArrayMap<>();
+
+            synchronized (mRootsLock) {
+                roots.putAll(mRoots);
+            }
+
+            // block root of storage
+            for (int i = 0; i < roots.size(); i++) {
+                RootInfo rootInfo = roots.valueAt(i);
+                // skip home root
+                if (TextUtils.equals(rootInfo.rootId, ROOT_ID_HOME)) {
+                    continue;
+                }
+
+                // block the root of storage
+                if (TextUtils.equals(path, rootInfo.visiblePath.getAbsolutePath())) {
+                    return true;
+                }
+            }
+            return false;
+        } catch (IOException e) {
+            throw new IllegalArgumentException(
+                    "Failed to determine if " + docId + " should block from tree " + ": " + e);
+        }
+    }
+
     @Override
     protected String getDocIdForFile(File file) throws FileNotFoundException {
         return getDocIdForFileMaybeCreate(file, false);
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
index 4408ef5..50f858e 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
@@ -16,6 +16,7 @@
 
 package com.android.localtransport;
 
+import android.annotation.Nullable;
 import android.app.backup.BackupAgent;
 import android.app.backup.BackupDataInput;
 import android.app.backup.BackupDataOutput;
@@ -71,19 +72,19 @@
 
     // Size quotas at reasonable values, similar to the current cloud-storage limits
     private static final long FULL_BACKUP_SIZE_QUOTA = 25 * 1024 * 1024;
-    private static final long KEY_VALUE_BACKUP_SIZE_QUOTA = 5 * 1024 * 1024;
+    protected static final long KEY_VALUE_BACKUP_SIZE_QUOTA = 5 * 1024 * 1024;
 
     private Context mContext;
     private File mDataDir;
     private File mCurrentSetDir;
-    private File mCurrentSetIncrementalDir;
+    protected File mCurrentSetIncrementalDir;
     private File mCurrentSetFullDir;
 
-    private PackageInfo[] mRestorePackages = null;
-    private int mRestorePackage = -1;  // Index into mRestorePackages
-    private int mRestoreType;
+    protected PackageInfo[] mRestorePackages = null;
+    protected int mRestorePackage = -1;  // Index into mRestorePackages
+    protected int mRestoreType;
     private File mRestoreSetDir;
-    private File mRestoreSetIncrementalDir;
+    protected File mRestoreSetIncrementalDir;
     private File mRestoreSetFullDir;
 
     // Additional bookkeeping for full backup
@@ -115,7 +116,7 @@
         makeDataDirs();
     }
 
-    LocalTransportParameters getParameters() {
+    public LocalTransportParameters getParameters() {
         return mParameters;
     }
 
@@ -142,11 +143,18 @@
         return null;
     }
 
+    /** @removed Replaced with dataManagementIntentLabel in the API */
     public String dataManagementLabel() {
         return TRANSPORT_DATA_MANAGEMENT_LABEL;
     }
 
     @Override
+    @Nullable
+    public CharSequence dataManagementIntentLabel() {
+        return TRANSPORT_DATA_MANAGEMENT_LABEL;
+    }
+
+    @Override
     public String transportDirName() {
         return TRANSPORT_DIR_NAME;
     }
@@ -537,14 +545,14 @@
         int bytesLeft = numBytes;
         while (bytesLeft > 0) {
             try {
-            int nRead = mSocketInputStream.read(mFullBackupBuffer, 0, bytesLeft);
-            if (nRead < 0) {
-                // Something went wrong if we expect data but saw EOD
-                Log.w(TAG, "Unexpected EOD; failing backup");
-                return TRANSPORT_ERROR;
-            }
-            mFullBackupOutputStream.write(mFullBackupBuffer, 0, nRead);
-            bytesLeft -= nRead;
+                int nRead = mSocketInputStream.read(mFullBackupBuffer, 0, bytesLeft);
+                if (nRead < 0) {
+                    // Something went wrong if we expect data but saw EOD
+                    Log.w(TAG, "Unexpected EOD; failing backup");
+                    return TRANSPORT_ERROR;
+                }
+                mFullBackupOutputStream.write(mFullBackupBuffer, 0, nRead);
+                bytesLeft -= nRead;
             } catch (IOException e) {
                 Log.e(TAG, "Error handling backup data for " + mFullTargetPackage);
                 return TRANSPORT_ERROR;
@@ -620,20 +628,15 @@
         }
         if (mRestorePackages == null) throw new IllegalStateException("startRestore not called");
 
-        boolean found = false;
+        boolean found;
         while (++mRestorePackage < mRestorePackages.length) {
             String name = mRestorePackages[mRestorePackage].packageName;
 
             // If we have key/value data for this package, deliver that
             // skip packages where we have a data dir but no actual contents
-            String[] contents = (new File(mRestoreSetIncrementalDir, name)).list();
-            if (contents != null && contents.length > 0) {
-                if (DEBUG) {
-                    Log.v(TAG, "  nextRestorePackage(TYPE_KEY_VALUE) @ "
-                        + mRestorePackage + " = " + name);
-                }
+            found = hasRestoreDataForPackage(name);
+            if (found) {
                 mRestoreType = RestoreDescription.TYPE_KEY_VALUE;
-                found = true;
             }
 
             if (!found) {
@@ -664,6 +667,18 @@
         return RestoreDescription.NO_MORE_PACKAGES;
     }
 
+    protected boolean hasRestoreDataForPackage(String packageName) {
+        String[] contents = (new File(mRestoreSetIncrementalDir, packageName)).list();
+        if (contents != null && contents.length > 0) {
+            if (DEBUG) {
+                Log.v(TAG, "  nextRestorePackage(TYPE_KEY_VALUE) @ "
+                        + mRestorePackage + " = " + packageName);
+            }
+            return true;
+        }
+        return false;
+    }
+
     @Override
     public int getRestoreData(ParcelFileDescriptor outFd) {
         if (mRestorePackages == null) throw new IllegalStateException("startRestore not called");
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
index 784be22..8b4db92 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
@@ -22,7 +22,7 @@
 import android.provider.Settings;
 import android.util.KeyValueListParser;
 
-class LocalTransportParameters extends KeyValueSettingObserver {
+public class LocalTransportParameters extends KeyValueSettingObserver {
     private static final String TAG = "LocalTransportParams";
     private static final String SETTING = Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS;
     private static final String KEY_FAKE_ENCRYPTION_FLAG = "fake_encryption_flag";
@@ -31,7 +31,7 @@
     private boolean mFakeEncryptionFlag;
     private boolean mIsNonIncrementalOnly;
 
-    LocalTransportParameters(Handler handler, ContentResolver resolver) {
+    public LocalTransportParameters(Handler handler, ContentResolver resolver) {
         super(handler, resolver, Settings.Secure.getUriFor(SETTING));
     }
 
diff --git a/packages/PrintSpooler/TEST_MAPPING b/packages/PrintSpooler/TEST_MAPPING
new file mode 100644
index 0000000..4fa8822
--- /dev/null
+++ b/packages/PrintSpooler/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsPrintTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        }
+      ]
+    }
+  ]
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
index a18600a..2b84196 100644
--- a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
@@ -48,11 +48,21 @@
         return getEnabledServicesFromSettings(context, UserHandle.myUserId());
     }
 
+    /**
+     * Check if the accessibility service is crashed
+     *
+     * @param packageName The package name to check
+     * @param serviceName The service name to check
+     * @param installedServiceInfos The list of installed accessibility service
+     * @return {@code true} if the accessibility service is crashed for the user.
+     * {@code false} otherwise.
+     */
     public static boolean hasServiceCrashed(String packageName, String serviceName,
-            List<AccessibilityServiceInfo> enabledServiceInfos) {
-        for (int i = 0; i < enabledServiceInfos.size(); i++) {
-            AccessibilityServiceInfo accessibilityServiceInfo = enabledServiceInfos.get(i);
-            final ServiceInfo serviceInfo = enabledServiceInfos.get(i).getResolveInfo().serviceInfo;
+            List<AccessibilityServiceInfo> installedServiceInfos) {
+        for (int i = 0; i < installedServiceInfos.size(); i++) {
+            final AccessibilityServiceInfo accessibilityServiceInfo = installedServiceInfos.get(i);
+            final ServiceInfo serviceInfo =
+                    installedServiceInfos.get(i).getResolveInfo().serviceInfo;
             if (TextUtils.equals(serviceInfo.packageName, packageName)
                     && TextUtils.equals(serviceInfo.name, serviceName)) {
                 return accessibilityServiceInfo.crashed;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
index 5d2a0d1d..e936c35 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
@@ -8,6 +8,7 @@
 
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.OpEntry;
+import android.app.AppOpsManager.OpFeatureEntry;
 import android.app.AppOpsManager.PackageOps;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -17,6 +18,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.LongSparseLongArray;
+import android.util.Pair;
 
 import org.junit.Before;
 import org.junit.Ignore;
@@ -161,7 +163,10 @@
         accessTimes.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_BACKGROUND,
             AppOpsManager.OP_FLAG_SELF), time);
 
-        return new OpEntry(op, false, AppOpsManager.MODE_ALLOWED, accessTimes, null /*durations*/,
-            null /*rejectTimes*/, null /* proxyUids */, null /* proxyPackages */);
+        OpFeatureEntry.Builder featureEntry = new OpFeatureEntry.Builder(false, accessTimes,
+                null /*rejectTimes*/, null /*durations*/, null /* proxyUids */,
+                null /* proxyPackages */, null /* proxyFeatureIds */);
+        return new OpEntry(op, AppOpsManager.MODE_ALLOWED,
+                new Pair[]{new Pair(null, featureEntry)});
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
index 7a553fc..3fde48b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
@@ -7,6 +7,7 @@
 
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.OpEntry;
+import android.app.AppOpsManager.OpFeatureEntry;
 import android.app.AppOpsManager.PackageOps;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -17,6 +18,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.LongSparseLongArray;
+import android.util.Pair;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -162,7 +164,11 @@
         final LongSparseLongArray durations = new LongSparseLongArray();
         durations.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_TOP,
                 AppOpsManager.OP_FLAG_SELF), duration);
-        return new OpEntry(op, false, AppOpsManager.MODE_ALLOWED, accessTimes,
-                null /*rejectTimes*/, durations, null /* proxyUids */, null /* proxyPackages */);
+
+        OpFeatureEntry.Builder featureEntry = new OpFeatureEntry.Builder(false, accessTimes,
+                null /*rejectTimes*/, durations, null /* proxyUids */,
+                null /* proxyPackages */, null /* proxyFeatureIds */);
+        return new OpEntry(op, AppOpsManager.MODE_ALLOWED,
+                new Pair[]{new Pair(null, featureEntry)});
     }
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/OWNERS b/packages/SettingsProvider/src/android/provider/settings/OWNERS
new file mode 100644
index 0000000..541dd878
--- /dev/null
+++ b/packages/SettingsProvider/src/android/provider/settings/OWNERS
@@ -0,0 +1,5 @@
+# Please reach out to Android B&R when making Settings backup changes
+alsutton@google.com
+nathch@google.com
+rthakohov@google.com
+
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/DeviceSpecificSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/DeviceSpecificSettings.java
new file mode 100644
index 0000000..e425790
--- /dev/null
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/DeviceSpecificSettings.java
@@ -0,0 +1,36 @@
+/*
+ * 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 android.provider.settings.backup;
+
+import android.provider.Settings;
+
+/** Device specific settings list */
+public class DeviceSpecificSettings {
+    /**
+     * The settings values which should only be restored if the target device is the
+     * same as the source device
+     *
+     * NOTE: Settings are backed up and restored in the order they appear
+     *       in this array. If you have one setting depending on another,
+     *       make sure that they are ordered appropriately.
+     *
+     * @hide
+     */
+    public static final String[] DEVICE_SPECIFIC_SETTINGS_TO_BACKUP = {
+            Settings.Secure.DISPLAY_DENSITY_FORCED,
+    };
+}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 976f336..ef67bbd 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -41,8 +41,8 @@
 public class SecureSettingsValidators {
     /**
      * All settings in {@link Secure.SETTINGS_TO_BACKUP} and {@link
-     * Secure.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP} array *must* have a non-null validator, otherwise
-     * they won't be restored.
+     * DeviceSpecificSettings.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP} array *must* have a non-null
+     * validator, otherwise they won't be restored.
      */
     public static final Map<String, Validator> VALIDATORS = new ArrayMap<>();
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 5e2b7c8..17c621e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -51,6 +51,7 @@
 import com.android.internal.util.XmlUtils;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockPatternView;
+import com.android.internal.widget.LockscreenCredential;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -1992,8 +1993,11 @@
                 try {
                     LockPatternUtils lpu = new LockPatternUtils(mContext);
                     List<LockPatternView.Cell> cellPattern =
-                            LockPatternUtils.stringToPattern(lockPattern);
-                    lpu.saveLockPattern(cellPattern, null, UserHandle.USER_SYSTEM);
+                            LockPatternUtils.byteArrayToPattern(lockPattern.getBytes());
+                    lpu.setLockCredential(
+                            LockscreenCredential.createPattern(cellPattern),
+                            LockscreenCredential.createNone(),
+                            UserHandle.USER_SYSTEM);
                 } catch (IllegalArgumentException e) {
                     // Don't want corrupted lock pattern to hang the reboot process
                 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index f545fa6..7e60452 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -34,6 +34,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.provider.settings.backup.DeviceSpecificSettings;
 import android.provider.settings.backup.GlobalSettings;
 import android.provider.settings.backup.SecureSettings;
 import android.provider.settings.backup.SystemSettings;
@@ -641,7 +642,7 @@
         if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
             whitelist = ArrayUtils.concatElements(String.class, SecureSettings.SETTINGS_TO_BACKUP,
                     Settings.Secure.LEGACY_RESTORE_SETTINGS,
-                    Settings.Secure.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP);
+                    DeviceSpecificSettings.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP);
             validators = SecureSettingsValidators.VALIDATORS;
         } else if (contentUri.equals(Settings.System.CONTENT_URI)) {
             whitelist = ArrayUtils.concatElements(String.class, SystemSettings.SETTINGS_TO_BACKUP,
@@ -1000,7 +1001,7 @@
                      getContentResolver()
                              .query(Settings.Secure.CONTENT_URI, PROJECTION, null, null, null)) {
             return extractRelevantValues(
-                    cursor, Settings.Secure.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP);
+                    cursor, DeviceSpecificSettings.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP);
         }
     }
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index a9c466e..3b41c90 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3184,7 +3184,7 @@
                         } catch (SecurityException e) {
                             Slog.w(LOG_TAG, "Failed to notify for " + userId + ": " + uri, e);
                         }
-                        if (DEBUG || true) {
+                        if (DEBUG) {
                             Slog.v(LOG_TAG, "Notifying for " + userId + ": " + uri);
                         }
                     } break;
diff --git a/packages/SettingsProvider/test/src/android/provider/OWNERS b/packages/SettingsProvider/test/src/android/provider/OWNERS
new file mode 100644
index 0000000..f3241ea
--- /dev/null
+++ b/packages/SettingsProvider/test/src/android/provider/OWNERS
@@ -0,0 +1,4 @@
+per-file * = *
+
+# Please reach out to the Android B&R team for settings backup changes
+per-file SettingsBackupTest.java = alsutton@google.com, nathch@google.com, rthakohov@google.com
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 8437eae..62827bc 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -16,6 +16,8 @@
 
 package android.provider;
 
+import static android.provider.settings.backup.DeviceSpecificSettings.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP;
+
 import static com.google.android.collect.Sets.newHashSet;
 import static com.google.common.truth.Truth.assertWithMessage;
 
@@ -750,7 +752,7 @@
     public void secureSettingsBackedUpOrBlacklisted() {
         HashSet<String> keys = new HashSet<String>();
         Collections.addAll(keys, SecureSettings.SETTINGS_TO_BACKUP);
-        Collections.addAll(keys, Settings.Secure.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP);
+        Collections.addAll(keys, DEVICE_SPECIFIC_SETTINGS_TO_BACKUP);
         checkSettingsBackedUpOrBlacklisted(
                 getCandidateSettings(Settings.Secure.class),
                 keys,
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index 83acfa0..656827a 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -46,3 +46,6 @@
 #Android Auto
 stenning@google.com
 
+#Android TV
+rgl@google.com
+
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/HomeControlsPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/HomeControlsPlugin.java
index cac673f..c1d4b03 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/HomeControlsPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/HomeControlsPlugin.java
@@ -33,4 +33,9 @@
       * will add home controls to this space.
       */
     void sendParentGroup(ViewGroup group);
+
+    /**
+     * When visible, will poll for updates.
+     */
+    void setVisible(boolean visible);
 }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
index db026ca..6518924 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -186,6 +186,8 @@
             return toStringBuilder().toString();
         }
 
+        // Used in dumps to determine current state of a tile.
+        // This string may be used for CTS testing of tiles, so removing elements is discouraged.
         protected StringBuilder toStringBuilder() {
             final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('[');
             sb.append(",icon=").append(icon);
diff --git a/packages/SystemUI/res/drawable/ic_lightbulb_outline_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_lightbulb_outline_gm2_24px.xml
new file mode 100644
index 0000000..87684a3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_lightbulb_outline_gm2_24px.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M9,21c0,0.55 0.45,1 1,1h4c0.55,0 1,-0.45 1,-1v-1L9,20v1zM12,2C8.14,2 5,5.14 5,9c0,2.38 1.19,4.47 3,5.74L8,17c0,0.55 0.45,1 1,1h6c0.55,0 1,-0.45 1,-1v-2.26c1.81,-1.27 3,-3.36 3,-5.74 0,-3.86 -3.14,-7 -7,-7zM14.85,13.1l-0.85,0.6L14,16h-4v-2.3l-0.85,-0.6C7.8,12.16 7,10.63 7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,1.63 -0.8,3.16 -2.15,4.1z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/home_controls.xml b/packages/SystemUI/res/layout/home_controls.xml
new file mode 100644
index 0000000..bb971c2
--- /dev/null
+++ b/packages/SystemUI/res/layout/home_controls.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/home_controls_layout"
+    android:layout_width="match_parent"
+    android:layout_height="125dp"
+    android:layout_gravity="@integer/notification_panel_layout_gravity"
+    android:visibility="gone"
+    android:padding="8dp"
+    android:layout_margin="5dp"
+    android:background="?android:attr/colorBackgroundFloating"
+    android:orientation="vertical">
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 0e59a41..4869be1 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -51,17 +51,7 @@
             systemui:viewType="com.android.systemui.plugins.qs.QS" />
 
         <!-- Temporary area to test out home controls -->
-        <LinearLayout
-            android:id="@+id/home_controls_layout"
-            android:layout_width="match_parent"
-            android:layout_height="125dp"
-            android:layout_gravity="@integer/notification_panel_layout_gravity"
-            android:visibility="gone"
-            android:padding="8dp"
-            android:layout_margin="5dp"
-            android:background="?android:attr/colorBackgroundFloating"
-            android:orientation="vertical">
-        </LinearLayout>
+        <include layout="@layout/home_controls" />
 
         <com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
             android:id="@+id/notification_stack_scroller"
@@ -107,4 +97,4 @@
         android:background="@drawable/qs_navbar_scrim" />
 
     <include layout="@layout/status_bar_expanded_plugin_frame"/>
-</merge>
\ No newline at end of file
+</merge>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index b0b4615..e86fb70 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Stel invoer metodes op"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fisiese sleutelbord"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Gee <xliff:g id="APPLICATION">%1$s</xliff:g> toegang tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Laat <xliff:g id="APPLICATION">%1$s</xliff:g> toe om by <xliff:g id="USB_DEVICE">%2$s</xliff:g> in te gaan?\nOpneemtoestemming is nie aan hierdie program verleen nie, maar dit kan oudio deur hierdie USB-toestel vasvang."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Gee <xliff:g id="APPLICATION">%1$s</xliff:g> toegang tot <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Maak <xliff:g id="APPLICATION">%1$s</xliff:g> oop om <xliff:g id="USB_DEVICE">%2$s</xliff:g> te hanteer?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Maak <xliff:g id="APPLICATION">%1$s</xliff:g> oop om <xliff:g id="USB_DEVICE">%2$s</xliff:g> te hanteer?\nOpneemtoestemming is nie aan hierdie program verleen nie, maar dit kan oudio deur hierdie USB-toestel vasvang."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Maak <xliff:g id="APPLICATION">%1$s</xliff:g> oop om <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> te hanteer?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Geen geïnstalleerde programme werk met hierdie USB-toebehoorsel nie. Vind meer uit oor hierdie toebehoorsel by <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-toebehoorsel"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Bevestig"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tik op Bevestig om te voltooi"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Gestaaf"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Gebruik PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Gebruik patroon"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Gebruik wagwoord"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Verkeerde PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Verkeerde patroon"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Verkeerde wagwoord"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Te veel verkeerde pogings.\nProbeer oor <xliff:g id="NUMBER">%d</xliff:g> sekondes weer."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Raak die vingerafdruksensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Vingerafdrukikoon"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Soek tans vir jou …"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Kennisgewings"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flitslig"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera in gebruik"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiele data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datagebruik"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Oorblywende data"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index e423c6a..fed9b05 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"የግቤት ስልቶችን አዘጋጅ"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"የሚዳሰስ የቁልፍ ሰሌዳ"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_DEVICE">%2$s</xliff:g>ን እንዲደርስበት ይፈቀድለት?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_DEVICE">%2$s</xliff:g>ን እንዲደርስ ይፈቀድለት?\nይህ መተግበሪያ የመቅዳት ፈቃድ አልተሰጠውም፣ ነገር ግን በዩኤስቢ መሣሪያ በኩል ኦዲዮን መቅዳት ይችላል።"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ን እንዲደርስበት ይፈቀድለት?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ን እንዲይዘው <xliff:g id="APPLICATION">%1$s</xliff:g> ይክፈት?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> ን <xliff:g id="USB_DEVICE">%2$s</xliff:g> ለማስተናገድ ይከፈት?\nይህ መተግበሪያ የቅጂ ፈቃድ አልተሰጠውም ሆኖም ግን በዩኤስቢ መሣሪያ በኩል ኦዲዮን መቅዳት ይችላል።"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ን እንዲይዘው <xliff:g id="APPLICATION">%1$s</xliff:g> ይክፈት?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ምንም የተጫኑ መተግበሪያዎች ከዚህ የUSB ተቀጥላ ጋር አይሰሩም። በ<xliff:g id="URL">%1$s</xliff:g> ስለዚህ ተቀጥላ የበለጠ ለመረዳት።"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"የUSB  ተቀጥላ"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"ተረጋግጧል"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"ለማጠናቀቅ አረጋግጥን መታ ያድርጉ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"የተረጋገጠ"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ፒን ይጠቀሙ"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ሥርዓተ ጥለትን ተጠቀም"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"የይለፍ ቃልን ተጠቀም"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"የተሳሳተ ፒን"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"የተሳሳተ ሥርዓተ ጥለት"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"የተሳሳተ የይለፍ ቃል"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ከልክ በላይ ብዙ የተሳሳቱ ሙከራዎች።\nበ<xliff:g id="NUMBER">%d</xliff:g> ሰከንዶች ውስጥ እንደገና ይሞክሩ።"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"የጣት አሻራ ዳሳሹን ይንኩ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"የጣት አሻራ አዶ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"እርስዎን በመፈለግ ላይ…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ማሳወቂያዎች"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"የባትሪ ብርሃን"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ካሜራ ስራ ላይ ነው"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"የተንቀሳቃሽ ስልክ ውሂብ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"የውሂብ አጠቃቀም"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ቀሪ ውሂብ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 3b145105..b04df54 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"إعداد أسلوب الإدخال"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"لوحة مفاتيح فعلية"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"هل تريد السماح لتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"‏هل تريد السماح لتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟\nلم يتم منح هذا التطبيق إذن تسجيل، ولكن يمكنه تسجيل الصوت من خلال جهاز USB هذا."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"هل تريد السماح لتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>؟"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"هل تريد فتح <xliff:g id="APPLICATION">%1$s</xliff:g> للتعامل مع <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"‏هل تريد فتح تطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> للتعامل مع <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟\nلم يتم منح هذا التطبيق إذن تسجيل، ولكن يمكنه تسجيل الصوت من خلال جهاز USB هذا."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"هل تريد فتح تطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> للتعامل مع <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>؟"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"‏لا يعمل أي تطبيق مثبت مع ملحق UEB هذا. مزيد من المعلومات عن هذا الملحق على <xliff:g id="URL">%1$s</xliff:g>."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"‏ملحق USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"تمّ التأكيد."</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"يمكنك النقر على \"تأكيد\" لإكمال المهمة."</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"مصادقة"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"استخدام رقم تعريف شخصي"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"استخدام نقش"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"استخدام كلمة المرور"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"رقم تعريف شخصي خاطئ"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"نقش غير صحيح"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"كلمة مرور غير صحيحة"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"تم إجراء عدد كبير جدًا من المحاولات غير الصحيحة.\nأعد المحاولة خلال <xliff:g id="NUMBER">%d</xliff:g> ثانية."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"المس زر استشعار بصمة الإصبع"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"رمز بصمة الإصبع"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"جارٍ البحث عن وجهك…"</string>
@@ -388,8 +381,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"الإشعارات"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"الفلاش"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"الكاميرا قيد الاستخدام"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"بيانات الجوّال"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"استخدام البيانات"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"البيانات المتبقية"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index c3ca88a..7efb03c 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ইনপুট পদ্ধতি ছেট আপ কৰক"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"বাস্তৱিক কীব\'ৰ্ড"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ত প্ৰৱেশ কৰিবলৈ <xliff:g id="APPLICATION">%1$s</xliff:g>ক অনুমতি দিবনে?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g>ক <xliff:g id="USB_DEVICE">%2$s</xliff:g> এক্সেছ কৰিবলৈ অনুমতি দিবনে?\nএই এপ্‌টোক ৰেকর্ড কৰাৰ অনুমতি দিয়া হোৱা নাই কিন্তু ই এই ইউএছবি ডিভাইচটোৰ জৰিয়তে অডিঅ\' ৰেকর্ড কৰিব পাৰে।"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g>ক <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ত প্ৰৱেশ কৰিবলৈ অনুমতি দিবনে?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ক ব্যৱহাৰ কৰিবলৈ <xliff:g id="APPLICATION">%1$s</xliff:g>ক খোলেনে?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ক ব্যৱহাৰ কৰিবলৈ <xliff:g id="APPLICATION">%1$s</xliff:g>ক খোলেনে?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ইনষ্টল হৈ থকা কোনো এপে ইউএছবি সহায়ক সামগ্ৰীটো চলাব নোৱাৰে। এই সহায়ক সামগ্ৰীৰ বিষয়ে <xliff:g id="URL">%1$s</xliff:g>ৰ জৰিয়তে অধিক জানক৷"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"ইউএছবিৰ সহায়ক সামগ্ৰী"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"নিশ্চিত কৰিলে"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"সম্পূৰ্ণ কৰিবলৈ নিশ্চিত কৰক-ত টিপক"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"পিন ব্যৱহাৰ কৰক"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"আৰ্হি ব্যৱহাৰ কৰক"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"পাছৱৰ্ড ব্যৱহাৰ কৰক"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ভুল পিন"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ভুল আৰ্হি"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ভুল পাছৱৰ্ড"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"বহুসংখ্যক ভুল প্ৰয়াস।\n<xliff:g id="NUMBER">%d</xliff:g>ছেকেণ্ডত পুনৰ চেষ্টা কৰক।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো স্পৰ্শ কৰক"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ফিংগাৰপ্ৰিণ্ট আইকন"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"আপোনাৰ মুখমণ্ডল বিচাৰি আছে…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"জাননীসমূহ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ফ্লাশ্বলাইট"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"কেমেৰা ব্যৱহাৰ হৈ আছে"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ম’বাইল ডেটা"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ডেটা ব্যৱহাৰ"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"বাকী থকা ডেটা"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 67e24c5..9d85126 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Daxiletmə metodlarını ayarlayın"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fiziki klaviatura"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına giriş icazəsi verilsin?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına giriş icazəsi verilsin?\nBu tətbiqə qeydə almaq icazəsi verilməyib lakin, bu USB vasitəsilə səs yaza bilər."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> cihazına giriş icazəsi verilsin?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazını idarə etmək üçün <xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqi açılsın?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazını idarə etmək üçün <xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqi açılsın?\nBu tətbiqə yazmaq icazəsi verilməyib, lakin, bu USB vasitəsilə səs yaza bilər."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> cihazını idarə etmək üçün <xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqi açılsın?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Heç bir quraşdırılmış tətbiq bu USB aksesuar ilə işləmir. Bu aksesuar haqqında daha ətraflı məlumatı <xliff:g id="URL">%1$s</xliff:g> adresindən öyrənin"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB aksesuar"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Təsdiqləndi"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tamamlamaq üçün \"Təsdiq edin\" seçiminə toxunun"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Doğrulandı"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN istifadə edin"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Model istifadə edin"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Parol istifadə edin"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Yanlış PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Yanlış model"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Yanlış parol"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Həddindən çox yanlış cəhd.\n<xliff:g id="NUMBER">%d</xliff:g> saniyəyə yenidən cəhd edin."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Barmaq izi sensoruna klikləyin"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Barmaq izi ikonası"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Siz axtarılırsınız…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Bildirişlər"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"İşartı"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera istifadə olunur"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobil data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Data istifadəsi"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Qalan data"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 3def744..07c321d6 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Podesi metode unosa"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizička tastatura"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Želite li da dozvolite da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Želite li da dozvolite da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nOva aplikacija nema dozvolu za snimanje, ali bi mogla da snima zvuk pomoću ovog USB uređaja."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Želite li da dozvolite da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Želite li da otvorite aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> da biste koristili uređaj <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Želite li da otvorite aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> radi rukovanja uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nOva aplikacija nema dozvolu za snimanje, ali bi mogla da snima zvuk pomoću ovog USB uređaja."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Želite li da otvorite aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> da biste koristili uređaj <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Instalirane aplikacije ne funkcionišu sa ovim USB pomoćnim uređajem. Saznajte više o njemu na adresi <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB pomoćni uređaj"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potvrđeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Dodirnite Potvrdi da biste završili"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Identitet je potvrđen"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Koristite PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Koristite šablon"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Koristite lozinku"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Pogrešan PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Pogrešan šablon"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Pogrešna lozinka"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Previše netačnih pokušaja.\n Probajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sek."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dodirnite senzor za otisak prsta"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona otiska prsta"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Tražimo vas…"</string>
@@ -382,8 +375,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obaveštenja"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampa"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Koristi se kamera"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilni podaci"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Potrošnja podataka"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Preostala količina podataka"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index cdb4ddb..ec73200 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Налада метадаў уводу"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Фізічная клавіятура"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Дазволіць праграме <xliff:g id="APPLICATION">%1$s</xliff:g> доступ да прылады <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Даць праграме \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ да прылады \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nУ гэтай праграмы няма дазволу на запіс, аднак яна зможа запісваць аўдыя праз гэту прыладу USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Дазволіць праграме <xliff:g id="APPLICATION">%1$s</xliff:g> доступ да прылады <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Адкрыць праграму <xliff:g id="APPLICATION">%1$s</xliff:g> для працы з прыладай <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Адкрыць праграму \"<xliff:g id="APPLICATION">%1$s</xliff:g>\", каб выкарыстоўваць прыладу \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nУ гэтай праграмы няма дазволу на запіс, аднак яна зможа запісваць аўдыя праз гэту USB-прыладу."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Адкрыць праграму <xliff:g id="APPLICATION">%1$s</xliff:g> для працы з прыладай <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Няма ўсталяв. прыкл. для працы з гэтай прыл. USB. Больш падраб. пра гэтую прыл.: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-прылада"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Пацверджана"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Націсніце \"Пацвердзіць\", каб завяршыць"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Распазнана"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Увесці PIN-код"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Выкарыстаць узор разблакіроўкі"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Выкарыстаць пароль"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Няправільны PIN-код"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Няправільны ўзор разблакіроўкі"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Няправільны пароль"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Занадта шмат няўдалых спроб.\nПаспрабуйце зноў праз <xliff:g id="NUMBER">%d</xliff:g> с."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Дакраніцеся да сканера адбіткаў пальцаў"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Значок адбіткаў пальцаў"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Ідзе пошук вашага твару…"</string>
@@ -386,8 +379,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Апавяшчэнні"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Ліхтарык"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Камера выкарыстоўваецца"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мабільная перадача даных"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Выкарыстанне трафіка"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Засталося трафіку"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index cd22290..6eeae8f 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Методи на въвеждане: Настройка"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Физическа клавиатура"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Да се разреши ли на <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Наистина ли искате да разрешите на <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nНа приложението не е предоставено разрешение за записване, но е възможно да запише звук чрез това USB устройство."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Да се разреши ли на <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Да се използва ли <xliff:g id="APPLICATION">%1$s</xliff:g> за работата с/ъс <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Искате ли да използвате <xliff:g id="APPLICATION">%1$s</xliff:g> за работа с(ъс) <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nПриложението няма разрешение за записване, но може да записва звук чрез това USB устройство."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Да се използва ли <xliff:g id="APPLICATION">%1$s</xliff:g> за работата с/ъс <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Инстал. приложения не работят с този аксесоар за USB. Научете повече на адрес <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Аксесоар за USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Потвърдено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Докоснете „Потвърждаване“ за завършване"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Удостоверено"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Използване на ПИН"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Използване на фигура"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Използване на парола"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Грешен ПИН"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Грешна фигура"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Грешна парола"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Твърде много неправилни опити.\nОпитайте отново след <xliff:g id="NUMBER">%d</xliff:g> секунди."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Докоснете сензора за отпечатъци"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Икона за отпечатък"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Търсим ви…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Известия"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Фенерче"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Камерата се използва"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобилни данни"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Пренос на данни"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Оставащи данни"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 11a6e90..8e4e9a1 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ইনপুট পদ্ধতিগুলি সেট-আপ করুন"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ফিজিক্যাল কীবোর্ড"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> কে <xliff:g id="USB_DEVICE">%2$s</xliff:g> অ্যাক্সেস করতে দেবেন?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> অ্যাক্সেস করতে <xliff:g id="APPLICATION">%1$s</xliff:g>-কে কি অনুমতি দেবেন?\nএই অ্যাপকে রেকর্ড করার অনুমতি দেওয়া হয়নি কিন্তু USB ডিভাইসের মাধ্যমে সেটি অডিও রেকর্ড করতে পারে।"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> কে <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> অ্যাক্সেস করতে দেবেন?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ব্যবহার করার জন্য <xliff:g id="APPLICATION">%1$s</xliff:g> চালু করবেন?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> অ্যাক্সেস করার জন্য <xliff:g id="APPLICATION">%1$s</xliff:g> খুলবেন?\nএই অ্যাপকে রেকর্ড করার অনুমতি দেওয়া হয়নি কিন্তু USB ডিভাইসের মাধ্যমে সেটি অডিও রেকর্ড করতে পারে।"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ব্যবহার করার জন্য <xliff:g id="APPLICATION">%1$s</xliff:g> চালু করবেন?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ইনস্টল থাকা কোনো অ্যাপ্লিকেশান এই USB যন্ত্রাংশের সাথে কাজ করে না৷ <xliff:g id="URL">%1$s</xliff:g> এ এই যন্ত্রাংশের সম্পর্কে আরও জানুন৷"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB যন্ত্রাংশ"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"কনফার্ম করা হয়েছে"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"সম্পূর্ণ করতে \'কনফার্ম করুন\' বোতামে ট্যাপ করুন"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"প্রমাণীকৃত"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"পিন ব্যবহার করুন"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"প্যাটার্ন ব্যবহার করুন"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"পাসওয়ার্ড ব্যবহার করুন"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ভুল পিন"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ভুল প্যাটার্ন"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ভুল পাসওয়ার্ড"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"অনেকবার ভুল চেষ্টা করা হয়েছে। \n<xliff:g id="NUMBER">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"আঙ্গুলের ছাপের সেন্সর স্পর্শ করুন"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"আঙ্গুলের ছাপের আইকন"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"আপনার জন্য খোঁজা হচ্ছে…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"বিজ্ঞপ্তি"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ফ্ল্যাশলাইট"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ক্যামেরা ব্যবহার করা হচ্ছে"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"মোবাইল ডেটা"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ডেটার ব্যবহার"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"অবশিষ্ট ডেটা"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 7eaa9c4..c5f94bd 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Postavljanje načina unosa"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizička tastatura"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Dozvoliti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Dozvoliti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nOvoj aplikaciji nije dato odobrenje za snimanje, ali može snimati zvuk putem ovog USB uređaja."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Dozvoliti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup dodatku: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Otvoriti aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> za upravljanje uređajem: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Želite li upravljati uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g> putem aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g>?\nOvoj aplikaciji nije dato odobrenje za snimanje, ali može snimati zvuk putem ovog USB uređaja."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Otvoriti aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> za upravljanje dodatkom: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Nema instaliranih aplikacija za ovaj USB uređaj. Saznajte više o uređaju na <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB periferni uređaj"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potvrđeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Dodirnite Potvrdi da završite"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentificirano"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Koristi PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Koristi uzorak"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Koristi lozinku"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Pogrešan PIN kôd"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Pogrešan uzorak"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Pogrešna lozinka"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Previše pogrešnih pokušaja.\n Pokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dodirnite senzor za otisak prsta"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona za otisak prsta"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Tražimo vas…"</string>
@@ -382,8 +375,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obavještenja"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svjetiljka"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera u upotrebi"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Prijenos podataka na mobilnoj mreži"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Prijenos podataka"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Preostala količina podataka"</string>
@@ -480,7 +472,7 @@
     <string name="media_projection_dialog_title" msgid="8124184308671641248">"Izlaganje osjetljivih podataka za vrijeme emitiranja/snimanja"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Ne prikazuj opet"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Očisti sve"</string>
-    <string name="manage_notifications_text" msgid="2386728145475108753">"Upravljaj"</string>
+    <string name="manage_notifications_text" msgid="2386728145475108753">"Upravljajte"</string>
     <string name="notification_section_header_gentle" msgid="4372438504154095677">"Nečujna obavještenja"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"Obriši sva nečujna obavještenja"</string>
     <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Obavještenja su pauzirana načinom rada Ne ometaj"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 3bd72b3..2ae91dd 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configura els mètodes d\'entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclat físic"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Vols permetre que <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vols permetre que <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAquesta aplicació no té permís de gravació, però pot capturar àudio a través d\'aquest dispositiu USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Vols permetre que <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vols obrir <xliff:g id="APPLICATION">%1$s</xliff:g> per gestionar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vols obrir <xliff:g id="APPLICATION">%1$s</xliff:g> per gestionar <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Les aplicacions instal·lades no funcionen amb l\'accessori USB. Més informació: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accessori USB"</string>
@@ -110,8 +111,8 @@
     <string name="accessibility_phone_button" msgid="6738112589538563574">"Telèfon"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Assistència per veu"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Desbloqueja"</string>
-    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"S\'està esperant l\'empremta digital"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Desbloqueja sense utilitzar l\'empremta digital"</string>
+    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"S\'està esperant l\'empremta dactilar"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Desbloqueja sense utilitzar l\'empremta dactilar"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"S\'està escanejant la cara"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Envia"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Gestiona les notificacions"</string>
@@ -128,22 +129,15 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmat"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Toca Confirma per completar"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticat"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
-    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca el sensor d\'empremtes digitals"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icona d\'empremta digital"</string>
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Utilitza el PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Utilitza el patró"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Utilitza la contrasenya"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN incorrecte"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Patró incorrecte"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Contrasenya incorrecta"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Has superat el nombre d\'intents incorrectes permesos.\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER">%d</xliff:g> segons."</string>
+    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca el sensor d\'empremtes dactilars"</string>
+    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icona d\'empremta dactilar"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"S\'està cercant la teva cara…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Icona facial"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botó de zoom de compatibilitat."</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificacions"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Llanterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Càmera en ús"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dades mòbils"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Ús de dades"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dades restants"</string>
@@ -477,7 +470,7 @@
     <string name="media_projection_dialog_title" msgid="8124184308671641248">"Es mostra informació sensible durant l\'emissió o la gravació"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"No ho tornis a mostrar"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Esborra-ho tot"</string>
-    <string name="manage_notifications_text" msgid="2386728145475108753">"Gestió"</string>
+    <string name="manage_notifications_text" msgid="2386728145475108753">"Gestiona"</string>
     <string name="notification_section_header_gentle" msgid="4372438504154095677">"Notificacions silencioses"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"Esborra totes les notificacions silencioses"</string>
     <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notificacions pausades pel mode No molestis"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index b3a8596..916986f 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nastavit metody zadávání"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fyzická klávesnice"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTato aplikace nemá oprávnění k nahrávání, ale může zaznamenávat zvuk prostřednictvím tohoto zařízení USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k zařízení <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Otevřít aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> ke správě zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Otevřít aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> ke správě zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTato aplikace nemá oprávnění k nahrávání, ale může zaznamenávat zvuk prostřednictvím tohoto zařízení USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Otevřít aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> ke správě zařízení <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Žádná nainstalovaná aplikace s tímto zařízením USB nepracuje. Info. najdete na <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Periferní zařízení USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potvrzeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Ověření dokončíte klepnutím na Potvrdit"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Ověřeno"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Použít kód PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Použít gesto"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Použít heslo"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Nesprávný kód PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Nesprávné gesto"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Nesprávné heslo"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Příliš mnoho neplatných pokusů.\nZkuste to znovu za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dotkněte se snímače otisků prstů"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona otisku prstu"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Hledáme vás…"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Oznámení"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svítilna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Fotoaparát se používá"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilní data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Využití dat"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Zbývající data"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index f0e5898..99fa80e 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfigurer inputmetoder"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fysisk tastatur"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Vil du give <xliff:g id="APPLICATION">%1$s</xliff:g> adgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vil du give <xliff:g id="APPLICATION">%1$s</xliff:g> adgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne app har ikke fået tilladelse til at optage, men optager muligvis lyd via denne USB-enhed."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Vil du give <xliff:g id="APPLICATION">%1$s</xliff:g> adgang til <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vil du åbne <xliff:g id="APPLICATION">%1$s</xliff:g> til håndtering af <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Vil du åbne <xliff:g id="APPLICATION">%1$s</xliff:g> for at håndtere <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne app har ikke fået tilladelse til at optage, men optager muligvis lyd via denne USB-enhed."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vil du åbne <xliff:g id="APPLICATION">%1$s</xliff:g> til håndtering af <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Ingen installerede apps fungerer sammen med USB-enheden. Få oplysninger om enheden på <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-ekstraudstyr"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Bekræftet"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tryk på Bekræft for at udføre"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Godkendt"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Brug pinkode"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Brug mønster"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Brug adgangskode"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Forkert pinkode"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Forkert mønster"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Forkert adgangskode"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"For mange mislykkede forsøg. \nPrøv igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Sæt fingeren på fingeraftrykslæseren"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon for fingeraftryk"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Forsøger at finde dig…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifikationer"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lommelygte"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kameraet er i brug"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobildata"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Dataforbrug"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Resterende data"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index f32c577..aced5d7 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Eingabemethoden festlegen"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Physische Tastatur"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> den Zugriff auf <xliff:g id="USB_DEVICE">%2$s</xliff:g> gewähren?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Der App \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" Zugriff auf das Gerät \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\" geben?\nDiese App hat noch nicht die Berechtigung zum Aufnehmen erhalten, könnte jedoch Audio über dieses USB-Gerät aufnehmen."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> den Zugriff auf <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> gewähren?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Für <xliff:g id="USB_DEVICE">%2$s</xliff:g> <xliff:g id="APPLICATION">%1$s</xliff:g> öffnen?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> öffnen, um <xliff:g id="USB_DEVICE">%2$s</xliff:g> zu bedienen?\nDiese App hat noch keine Berechtigung zum Aufnehmen erhalten, könnte aber Audioaufnahmen über dieses USB-Gerät machen."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Für <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> <xliff:g id="APPLICATION">%1$s</xliff:g> öffnen?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Keine installierten Apps für dieses USB-Zubehör. Weitere Informationen unter <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-Zubehör"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Bestätigt"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Zum Abschließen auf \"Bestätigen\" tippen"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authentifiziert"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN verwenden"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Muster verwenden"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Passwort verwenden"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Falsche PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Falsches Muster"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Falsches Passwort"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Zu viele Fehlversuche.\nBitte probiere es in <xliff:g id="NUMBER">%d</xliff:g> Sekunden noch einmal."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Berühre den Fingerabdrucksensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerabdruck-Symbol"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Wir suchen nach dir…"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Benachrichtigungen"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Taschenlampe"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera wird verwendet"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile Daten"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datennutzung"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Verbleibende Daten"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index ce693ee..044d396 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Ρύθμιση μεθόδων εισαγωγής"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Φυσικό πληκτρολόγιο"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Να επιτρέπεται η πρόσβαση της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> στη συσκευή <xliff:g id="USB_DEVICE">%2$s</xliff:g>;"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Να επιτρέπεται στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> να έχει πρόσβαση στη συσκευή <xliff:g id="USB_DEVICE">%2$s</xliff:g>;\nΔεν έχει εκχωρηθεί άδεια εγγραφής σε αυτήν την εφαρμογή, αλλά μέσω αυτής της συσκευής USB θα μπορεί να εγγράφει ήχο."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Να επιτρέπεται η πρόσβαση της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> στο αξεσουάρ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>;"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Να ανοίγει η εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> για τη διαχείριση της συσκευής <xliff:g id="USB_DEVICE">%2$s</xliff:g>;"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Άνοιγμα της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> για τον χειρισμό της συσκευής <xliff:g id="USB_DEVICE">%2$s</xliff:g>;\nΔεν έχει εκχωρηθεί άδεια εγγραφής σε αυτήν την εφαρμογή, αλλά μέσω αυτής της συσκευής USB θα μπορεί να εγγράφει ήχο."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Να ανοίγει η εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> για τη διαχείριση του αξεσουάρ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>;"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Δεν έχετε εφαρμογή που να συνεργάζεται με το αξεσουάρ USB. Για περισσότερα: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Αξεσουάρ USB"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Φωνητική υποβοήθηση"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Ξεκλείδωμα"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Αναμονή για δακτυλικό αποτύπωμα"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Ξεκλείδωμα χωρίς τη χρήση του μοναδικού χαρακτηριστικού σας"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Ξεκλείδωμα χωρίς τη χρήση του δακτυλικού αποτυπώματός σας"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"Σάρωση προσώπου"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Αποστολή"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Διαχείριση ειδοποιήσεων"</string>
@@ -128,21 +128,14 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Επιβεβαιώθηκε"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Πατήστε Επιβεβαίωση για ολοκλήρωση"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Ολοκληρώθηκε ο έλεγχος ταυτότητας"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
-    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Αγγίξτε τον αισθητήρα δακτυλικών αποτυπωμάτων"</string>
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Χρήση PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Χρήση μοτίβου"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Χρήση κωδικού πρόσβασης"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Εσφαλμένο PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Εσφαλμένο μοτίβο"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Εσφαλμένος κωδικός πρόσβασης"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Πάρα πολλές αποτυχημένες προσπάθειες.\nΔοκιμάστε ξανά σε <xliff:g id="NUMBER">%d</xliff:g> δευτερόλεπτα."</string>
+    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Αγγίξτε τον αισθητήρα δακτυλικού αποτυπώματος"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Εικονίδιο δακτυλικών αποτυπωμάτων"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Αναζήτηση για εσάς…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Εικονίδιο προσώπου"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ειδοποιήσεις"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Φακός"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Η κάμερα χρησιμοποιείται"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Δεδομένα κινητής τηλεφωνίας"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Χρήση δεδομένων"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Υπολειπόμενα δεδομένα"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 013b4cb..5bf1b0f 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -50,6 +50,7 @@
     <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"No installed apps work with this USB accessory. Learn more about this accessory at <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB accessory"</string>
@@ -127,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tap Confirm to complete"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authenticated"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Use PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Use pattern"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Use password"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Wrong PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Wrong pattern"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Wrong password"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerprint icon"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Looking for you…"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index a21ecb49..a327151 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -50,6 +50,7 @@
     <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"No installed apps work with this USB accessory. Learn more about this accessory at <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB accessory"</string>
@@ -127,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tap Confirm to complete"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authenticated"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Use PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Use pattern"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Use password"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Wrong PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Wrong pattern"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Wrong password"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerprint icon"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Looking for you…"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 013b4cb..5bf1b0f 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -50,6 +50,7 @@
     <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"No installed apps work with this USB accessory. Learn more about this accessory at <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB accessory"</string>
@@ -127,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tap Confirm to complete"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authenticated"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Use PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Use pattern"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Use password"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Wrong PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Wrong pattern"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Wrong password"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerprint icon"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Looking for you…"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 013b4cb..5bf1b0f 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -50,6 +50,7 @@
     <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"No installed apps work with this USB accessory. Learn more about this accessory at <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB accessory"</string>
@@ -127,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tap Confirm to complete"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authenticated"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Use PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Use pattern"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Use password"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Wrong PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Wrong pattern"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Wrong password"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerprint icon"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Looking for you…"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index d8cfb30..15617b3 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -50,6 +50,7 @@
     <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‎‎‏‏‎‎‎‎‏‏‎Allow ‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to access ‎‏‎‎‏‏‎<xliff:g id="USB_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎This app has not been granted record permission but could capture audio through this USB device.‎‏‎‎‏‎"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‏‎‏‏‎‏‎‏‏‏‎Allow ‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to access ‎‏‎‎‏‏‎<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‏‎‎‏‎‎‎‎‎‎‏‎Open ‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to handle ‎‏‎‎‏‏‎<xliff:g id="USB_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‏‏‏‏‎‎‎‏‎Open ‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to handle ‎‏‎‎‏‏‎<xliff:g id="USB_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎This app has not been granted record permission but could capture audio through this USB device.‎‏‎‎‏‎"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎Open ‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to handle ‎‏‎‎‏‏‎<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎No installed apps work with this USB accessory. Learn more about this accessory at ‎‏‎‎‏‏‎<xliff:g id="URL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‎‎‏‏‎‎‎‎‏‎‏‏‏‏‎‎‎USB accessory‎‏‎‎‏‎"</string>
@@ -127,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‎Confirmed‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎Tap Confirm to complete‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‏‎‏‎‎‎‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‏‏‏‎‏‎Authenticated‎‏‎‎‏‎"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‎Use PIN‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎Use pattern‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎Use password‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‏‏‏‎‎Wrong PIN‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎Wrong pattern‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‎Wrong password‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎Too many incorrect attempts.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‏‎Touch the fingerprint sensor‎‏‎‎‏‎"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‎‎Fingerprint icon‎‏‎‎‏‎"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‏‏‎‎‎‎‏‎Looking for you…‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 4b2943c..a69de3b 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de intro."</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"¿Deseas permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"¿Quieres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLa app no tiene permiso para grabar, pero podría capturar audio mediante este dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"¿Deseas permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"¿Deseas abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para usar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"¿Quieres abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para administrar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLa app no tiene permiso para grabar, pero puede capturar audio mediante este dispositivo USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"¿Deseas abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para usar <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Ninguna aplic. funciona con este accesorio USB. Más info. acerca de este en <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accesorio USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmado"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Presiona Confirmar para completarla"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticado"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Usar PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Usar patrón"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Usar contraseña"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN incorrecto"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Patrón incorrecto"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Contraseña incorrecta"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Demasiados intentos incorrectos.\nVuelve a intentarlo en <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca el sensor de huellas digitales"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ícono de huella digital"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Autenticando tu rostro…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificaciones"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Linterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Cámara en uso"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Datos móviles"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Uso de datos"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Datos restantes"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 903c50a..f96f7b9 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"¿Quieres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"¿Quieres que <xliff:g id="APPLICATION">%1$s</xliff:g> pueda acceder a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsta aplicación no tiene permisos para grabar, pero podría captar audio a través de este dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"¿Quieres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"¿Quieres abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para utilizar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"¿Quieres abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para utilizar <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Ninguna aplicación instalada funciona con este accesorio USB. Más información: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accesorio USB"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Toca Confirmar para completar la acción"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Se ha autenticado"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Usar PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Usar patrón"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Usar contraseña"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN incorrecto"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Patrón incorrecto"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Contraseña incorrecta"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Demasiados intentos fallidos.\n Vuelve a intentarlo en <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca el sensor de huellas digitales"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icono de huella digital"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Buscando tu cara…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificaciones"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Linterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Cámara en uso"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Datos móviles"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Uso de datos"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Datos restantes"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 113b207..b106a01 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Seadista sisestusmeetodeid"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Füüsiline klaviatuur"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Kas lubada rakendusele <xliff:g id="APPLICATION">%1$s</xliff:g> juurdepääs seadmele <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Kas lubada rakendusel <xliff:g id="APPLICATION">%1$s</xliff:g> seadmele <xliff:g id="USB_DEVICE">%2$s</xliff:g> juurde pääseda?\nSellele rakendusele pole antud salvestamise luba, kuid see saab heli jäädvustada selle USB-seadme kaudu."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Kas lubada rakendusele <xliff:g id="APPLICATION">%1$s</xliff:g> juurdepääs seadmele <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Kas avada rakendus <xliff:g id="APPLICATION">%1$s</xliff:g> seadme <xliff:g id="USB_DEVICE">%2$s</xliff:g> kasutamiseks?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Kas avada <xliff:g id="APPLICATION">%1$s</xliff:g>, et käsitseda seadet <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nSellele rakendusele pole antud salvestamise luba, kuid see saab heli jäädvustada selle USB-seadme kaudu."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Kas avada rakendus <xliff:g id="APPLICATION">%1$s</xliff:g> seadme <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> kasutamiseks?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Inst. rak. ei tööta selle USB-seadmega. Lisateavet lisaseadme kohta vt siit: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-lisaseade"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Kinnitatud"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Lõpuleviimiseks puudutage nuppu Kinnita"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenditud"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Kasuta PIN-koodi"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Kasuta mustrit"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Kasuta parooli"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Vale PIN-kood"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Vale muster"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Vale parool"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Liiga palju valesid katseid.\nProovige <xliff:g id="NUMBER">%d</xliff:g> sekundi pärast uuesti."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Puudutage sõrmejäljeandurit"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Sõrmejälje ikoon"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Otsitakse teid …"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Märguanded"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Taskulamp"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kasutusel olev kaamera"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiilne andmeside"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Andmeside kasutus"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Järelejäänud andmemaht"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index e541329..4e9fe245 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfiguratu idazketa-metodoak"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teklatu fisikoa"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> atzitzeko baimena eman nahi diozu <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioari?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> erabiltzeko baimena eman nahi diozu <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioari?\nAplikazioak ez du grabatzeko baimenik, baina baliteke USB bidezko gailu horren bidez audioa grabatzea."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> atzitzeko baimena eman nahi diozu <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioari?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="APPLICATION">%1$s</xliff:g> ireki nahi duzu <xliff:g id="USB_DEVICE">%2$s</xliff:g> kudeatzeko?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> ireki nahi duzu <xliff:g id="USB_DEVICE">%2$s</xliff:g> erabiltzeko?\nAplikazioak ez du grabatzeko baimenik, baina baliteke audioa grabatzea USB bidezko gailu horren bidez."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="APPLICATION">%1$s</xliff:g> ireki nahi duzu <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> kudeatzeko?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Instalatutako aplikazioek ez dute USB osagarri honekin funtzionatzen. Lortu informazio gehiago osagarriari buruz hemen: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB osagarria"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Berretsita"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Amaitzeko, sakatu \"Berretsi\""</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentifikatuta"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Erabili PIN kodea"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Erabili eredua"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Erabili pasahitza"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN kodea ez da zuzena"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Eredua ez da zuzena"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Pasahitza ez da zuzena"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Saiakera oker gehiegi egin dituzu.\nSaiatu berriro <xliff:g id="NUMBER">%d</xliff:g> segundo barru."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Sakatu hatz-marken sentsorea"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Hatz-markaren ikonoa"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Zure bila…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Jakinarazpenak"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Linterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera abian da"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Datu-konexioa"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datuen erabilera"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Geratzen diren datuak"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 232f7a2..1751cc9 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"تنظیم روش‌های ورودی"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"صفحه‌کلید فیزیکی"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"به <xliff:g id="APPLICATION">%1$s</xliff:g> برای دسترسی به <xliff:g id="USB_DEVICE">%2$s</xliff:g> اجازه داده شود؟"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"‏به <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه می‌دهید به <xliff:g id="USB_DEVICE">%2$s</xliff:g>دسترسی داشته باشد؟\nمجوز ضبط به این برنامه داده نشده است اما می‌تواند صدا را ازطریق این دستگاه USB ضبط کند."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"به <xliff:g id="APPLICATION">%1$s</xliff:g> برای دسترسی به <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> اجازه داده شود؟"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"برای استفاده از <xliff:g id="USB_DEVICE">%2$s</xliff:g>، <xliff:g id="APPLICATION">%1$s</xliff:g> باز شود؟"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"‏<xliff:g id="APPLICATION">%1$s</xliff:g> برای رسیدگی به <xliff:g id="USB_DEVICE">%2$s</xliff:g> باز شود؟\nمجوز ضبط به این برنامه داده نشده است اما می‌تواند صدا را ازطریق این دستگاه USB ضبط کند."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"برای استفاده از <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>، <xliff:g id="APPLICATION">%1$s</xliff:g> باز شود؟"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"‏هیچ برنامه نصب شده‌ای با این وسیله جانبی USB کار نمی‌کند. در <xliff:g id="URL">%1$s</xliff:g> دربارهٔ این وسیله جانبی اطلاعات بیشتری کسب کنید"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"‏لوازم جانبی USB"</string>
@@ -110,7 +110,7 @@
     <string name="accessibility_phone_button" msgid="6738112589538563574">"تلفن"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"دستیار صوتی"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"باز کردن قفل"</string>
-    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"در انتظار اثرانگشت"</string>
+    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"در انتظار اثر انگشت"</string>
     <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"باز کردن قفل بدون استفاده از اثر انگشت"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"درحال اسکن کردن چهره"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"ارسال"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"تأیید شد"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"برای تکمیل، روی تأیید ضربه بزنید"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"راستی‌آزمایی‌شده"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"استفاده از پین"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"استفاده از الگو"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"استفاده از گذرواژه"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"پین اشتباه است"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"الگو اشتباه است"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"گذرواژه اشتباه است"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"تلاش‌های نادرست بسیاری انجام شده است.\nپس از <xliff:g id="NUMBER">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"حسگر اثر انگشت را لمس کنید"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"نماد اثر انگشت"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"درحال جستجوی شما…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"اعلان‌ها"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"چراغ قوه"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"دوربین درحال استفاده"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"داده تلفن همراه"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"مصرف داده"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"داده‌های باقی‌مانده"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 5767c3c..c6c90b3 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Määritä syöttötavat"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fyysinen näppäimistö"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Saako <xliff:g id="APPLICATION">%1$s</xliff:g> käyttöoikeuden (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Saako <xliff:g id="APPLICATION">%1$s</xliff:g> tämän pääsyoikeuden: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nSovellus ei ole saanut tallennuslupaa, mutta voi tallentaa ääntä tämän USB-laitteen avulla."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Saako <xliff:g id="APPLICATION">%1$s</xliff:g> käyttöoikeuden (<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>)?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Avataanko <xliff:g id="APPLICATION">%1$s</xliff:g>, jotta <xliff:g id="USB_DEVICE">%2$s</xliff:g> voidaan ottaa käyttöön?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Avataanko <xliff:g id="APPLICATION">%1$s</xliff:g>, jotta <xliff:g id="USB_DEVICE">%2$s</xliff:g> voidaan ottaa käyttöön?\nSovellus ei ole saanut tallennuslupaa, mutta voi tallentaa ääntä tämän USB-laitteen avulla."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Avataanko <xliff:g id="APPLICATION">%1$s</xliff:g>, jotta <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> voidaan ottaa käyttöön?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Asennetut sov. eivät toimi tämän USB-laitteen kanssa. Lisätietoja laitteesta: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-lisälaite"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Vahvistettu"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Valitse lopuksi Vahvista"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Todennettu"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Käytä PIN-koodia"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Käytä kuviota"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Käytä salasanaa"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Väärä PIN-koodi"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Väärä kuvio"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Väärä salasana"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Liian monta virheellistä yritystä.\nYritä uudelleen <xliff:g id="NUMBER">%d</xliff:g> sekunnin kuluttua."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Kosketa sormenjälkitunnistinta"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Sormenjälkikuvake"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Etsitään kasvoja…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ilmoitukset"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Taskulamppu"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera käytössä"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiilidata"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datakäyttö"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"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 04138c0..01427c9 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurer les modes de saisie"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Clavier physique"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Autorisé <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nCette application n\'a pas été autorisée à effectuer des enregistrements, mais elle pourrait enregistrer du contenu audio par l\'intermédiaire de cet appareil USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour utiliser <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour gérer <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nCette application n\'a pas été autorisée à effectuer des enregistrements, mais elle pourrait enregistrer du contenu audio par l\'intermédiaire de cet appareil USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour utiliser <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Aucune application installée compatible avec accessoire USB. En savoir plus sur <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accessoire USB"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"Toujours ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> lorsque <xliff:g id="USB_DEVICE">%2$s</xliff:g> est connecté"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Toujours ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> lorsque <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> est connecté"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"Autoriser le débogage USB?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"Empreinte digitale numérique de la clé RSA de l\'ordinateur : \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Empreinte numérique de la clé RSA de l\'ordinateur : \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Toujours autoriser sur cet ordinateur"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"Autoriser"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Débogage USB non autorisé"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmé"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Touchez Confirmer pour terminer"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authentifié"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Utiliser un NIP"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Utiliser un schéma"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Utiliser un mot de passe"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"NIP incorrect"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Schéma incorrect"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Mot de passe incorrect"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Trop de tentatives incorrectes. \nRéessayez dans <xliff:g id="NUMBER">%d</xliff:g> secondes."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touchez le capteur d\'empreintes digitales"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icône d\'empreinte digitale"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Recherche de votre visage…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampe de poche"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"L\'appareil photo est en cours d\'utilisation"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Données cellulaires"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Utilisation de données"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Données restantes"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7191426..852bd11 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurer les modes de saisie"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Clavier physique"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?\nCette application n\'a pas été autorisée à effectuer des enregistrements, mais elle pourrait enregistrer du contenu audio via ce périphérique USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour utiliser <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour gérer <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?\nCette application n\'a pas reçu l\'autorisation d\'enregistrer des contenus audio, mais peut le faire via ce périphérique USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour utiliser <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Aucune application installée compatible avec accessoire USB. En savoir plus sur <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accessoire USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmé"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Appuyez sur \"Confirmer\" pour terminer"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authentifié"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Utiliser un code PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Utiliser un schéma"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Utiliser un mot de passe"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Code incorrect"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Schéma incorrect"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Mot de passe incorrect"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Trop de tentatives incorrectes.\nVeuillez réessayer dans <xliff:g id="NUMBER">%d</xliff:g> secondes."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Appuyez sur le lecteur d\'empreinte digitale"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icône d\'empreinte digitale"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Recherche de votre visage…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampe de poche"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Caméra en cours d\'utilisation"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Données mobiles"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Conso des données"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Données restantes"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 4262d88..885302e 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Queres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Queres permitir que a aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda ao dispositivo (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?\nEsta aplicación non está autorizada para realizar gravacións, pero pode capturar audio a través deste dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Queres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Queres abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para utilizar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Queres abrir a aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> para xestionar o dispositivo (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?\nEsta aplicación non está autorizada a realizar gravacións, pero pode capturar audio a través deste dispositivo USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Queres abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para utilizar <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Ningunha aplicación instalada funciona co accesorio USB. Máis información: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accesorio USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Toca Confirmar para completar o proceso"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticado"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Usar PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Usar padrón"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Usar contrasinal"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"O PIN é incorrecto"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"O padrón é incorrecto"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"O contrasinal é incorrecto"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Realizáronse demasiados intentos incorrectos.\nTéntao de novo en <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca o sensor de impresión dixital"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icona de impresión dixital"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Buscándote…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificacións"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Cámara en uso"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Datos móbiles"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Uso de datos"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Datos restantes"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 66f9a7a..b3ec665 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ઇનપુટ પદ્ધતિઓ સેટ કરો"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ભૌતિક કીબોર્ડ"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ના ઍક્સેસ માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને મંજૂરી આપીએ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g>ને <xliff:g id="USB_DEVICE">%2$s</xliff:g> ઍક્સેસ કરવાની મંજૂરી આપીએ?\nઆ ઍપને રેકૉર્ડ કરવાની પરવાનગી આપવામાં આવી નથી પરંતુ તે આ USB ડિવાઇસ મારફત ઑડિયો કૅપ્ચર કરી શકે છે."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ના ઍક્સેસ માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને મંજૂરી આપીએ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ને હૅન્ડલ કરવા માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને ખોલીએ?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ને હેન્ડલ કરવા માટે <xliff:g id="APPLICATION">%1$s</xliff:g> ખોલીએ?\nઆ ઍપને રેકૉર્ડ કરવાની પરવાનગી આપવામાં આવી નથી પરંતુ તે આ USB ડિવાઇસ મારફત ઑડિયો કૅપ્ચર કરી શકે છે."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ને હૅન્ડલ કરવા માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને ખોલીએ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"કોઈપણ ઇન્સ્ટોલ કરેલી ઍપ્લિકેશનો આ USB ઍક્સેસરી સાથે કામ કરતી નથી. આ ઍક્સેસરી વિશે <xliff:g id="URL">%1$s</xliff:g> પર વધુ જાણો."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB ઍક્સેસરી"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"પુષ્ટિ કરી"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"પરીક્ષણ પૂર્ણ કરવા કન્ફર્મ કરોને ટૅપ કરો"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"પ્રમાણિત"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"પિનનો ઉપયોગ કરો"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"પૅટર્નનો ઉપયોગ કરો"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"પાસવર્ડનો ઉપયોગ કરો"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ખોટો પિન"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ખોટી પૅટર્ન"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ખોટો પાસવર્ડ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ઘણા વધારે ખોટા પ્રયત્નો. \n <xliff:g id="NUMBER">%d</xliff:g> સેકંડમાં ફરી પ્રયાસ કરો."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ફિંગરપ્રિન્ટના સેન્સરને સ્પર્શ કરો"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ફિંગરપ્રિન્ટનું આઇકન"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"તમારા માટે શોધી રહ્યાં છે..."</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"નોટિફિકેશનો"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ફ્લેશલાઇટ"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"કૅમેરાનો ઉપયોગ થાય છે"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"મોબાઇલ ડેટા"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ડેટા વપરાશ"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"બાકી ડેટા"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index c49cae4..56117ed 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"इनपुट का तरीका सेट करें"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"सामान्य कीबोर्ड"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_DEVICE">%2$s</xliff:g> के ऐक्सेस की अनुमति दें?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_DEVICE">%2$s</xliff:g> ऐक्सेस करने की अनुमति देना चाहते हैं?\nइस ऐप्लिकेशन को रिकॉर्ड करने की अनुमति नहीं दी गई है. हालांकि, ऐप्लिकेशन इस यूएसबी डिवाइस से ऑडियो कैप्चर कर सकता है."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> के ऐक्सेस की अनुमति दें?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> के लिए <xliff:g id="APPLICATION">%1$s</xliff:g> खोलें?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> के लिए <xliff:g id="APPLICATION">%1$s</xliff:g> खोलें?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"इस USB सहायक डिवाइस के साथ कोई भी इंस्टॉल ऐप्स  काम नहीं करता. इस सहायक डिवाइस के बारे में यहां ज़्यादा जानें: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB सहायक साधन"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"पुष्टि हो गई"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"\'पुष्टि करें\' पर टैप करके पूरा करें"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"पुष्टि हो गई"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"पिन इस्तेमाल करें"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"पैटर्न इस्तेमाल करें"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"पासवर्ड इस्तेमाल करें"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"गलत पिन"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"गलत पैटर्न"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"गलत पासवर्ड"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"आपकी कोशिशें बहुत बार गलत हुई हैं.\nआप <xliff:g id="NUMBER">%d</xliff:g> सेकंड में फिर से कोशिश कर सकते हैं."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"फ़िंगरप्रिंट सेंसर को छुएं"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"फ़िंगरप्रिंट आइकॉन"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"आपको पहचान रहा है…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"सूचनाएं"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"फ़्लैशलाइट"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"कैमरा इस्तेमाल में है"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"मोबाइल डेटा"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"डेटा खर्च"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"शेष डेटा"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 6086764..96b1623 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Postavljanje načina unosa"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizička tipkovnica"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Želite li dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Želite li dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> da pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacija nema dopuštenje za snimanje, no mogla bi primati zvuk putem tog USB uređaja."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Želite li dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Želite li otvoriti aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> radi upravljanja uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Želite li upravljati uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g> putem aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g>?\nTa aplikacija nema dopuštenje za snimanje, no mogla bi primati zvuk putem tog USB uređaja."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Želite li otvoriti aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> radi upravljanja uređajem <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Nijedna instalirana aplikacija ne radi s ovim USB dodatkom. Saznajte više na <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB pribor"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potvrđeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Dodirnite Potvrdi za dovršetak"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentičnost provjerena"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Koristite PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Koristite uzorak"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Koristite zaporku"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Pogrešan PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Pogrešan uzorak"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Pogrešna zaporka"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Previše netočnih pokušaja.\nPokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dodirnite senzor otiska prsta"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona otiska prsta"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Tražimo vas…"</string>
@@ -382,8 +375,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obavijesti"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svjetiljka"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Upotrebljava se kamera"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilni podaci"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Potrošnja podataka"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Preostali podaci"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index be039c7..bd23d4d 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Beviteli módok beállítása"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizikai billentyűzet"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Engedélyezi a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> számára, hogy hozzáférjen a következőhöz: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Lehetővé teszi a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazásnak, hogy hozzáférjen a következőhöz: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEz az alkalmazás nem rendelkezik rögzítési engedéllyel, de ezzel az USB-eszközzel képes a hangfelvételre."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Engedélyezi a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> számára, hogy hozzáférjen a következőhöz: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Megnyitja a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazást a(z) <xliff:g id="USB_DEVICE">%2$s</xliff:g> kezeléséhez?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Megnyitja a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazást, hogy kezelje a következőt: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEz az alkalmazás nem rendelkezik rögzítési engedéllyel, de ezzel az USB-eszközzel képes a hangfelvételre."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Megnyitja a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazást a(z) <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> kezeléséhez?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"A telepített alkalmazások nem működnek ezzel az USB-kiegészítővel. Bővebben: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-kellék"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Megerősítve"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Koppintson a Megerősítés lehetőségre"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Hitelesítve"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN-kód használata"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Minta használata"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Jelszó használata"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Helytelen PIN-kód"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Helytelen minta"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Helytelen jelszó"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Túl sok helytelen próbálkozás.\nPróbálja újra <xliff:g id="NUMBER">%d</xliff:g> másodperc múlva."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Érintse meg az ujjlenyomat-érzékelőt"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ujjlenyomat ikonja"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Keresem az Ön arcát…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Értesítések"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Zseblámpa"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"A kamera használatban van"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiladatok"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Adathasználat"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Fennmaradó adatmennyiség"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 0f84b50..2647f2f 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Կարգավորել մուտքագրման եղանակները"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Ֆիզիկական ստեղնաշար"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Թույլատրե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին օգտագործել <xliff:g id="USB_DEVICE">%2$s</xliff:g> լրասարքը։"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Թույլատրե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին օգտագործել <xliff:g id="USB_DEVICE">%2$s</xliff:g>ը։\nՀավելվածը ձայնագրելու թույլտվություն չունի, սակայն կկարողանա գրանցել ձայնն այս USB սարքի միջոցով։"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Թույլատրե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին օգտագործել <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> լրասարքը։"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Բացե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը <xliff:g id="USB_DEVICE">%2$s</xliff:g> լրասարքը մշակելու համար։"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Բացե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը՝ <xliff:g id="USB_DEVICE">%2$s</xliff:g>ն օգտագործելու համար:\nՀավելվածը ձայնագրելու թույլտվություն չունի, սակայն կկարողանա գրանցել ձայնն այս USB սարքի միջոցով։"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Բացե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> լրասարքը մշակելու համար։"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Այս USB լրասարքի հետ ոչ մի հավելված չի աշխատում: Իմացեք ավելին այս լրասարքի մասին <xliff:g id="URL">%1$s</xliff:g>-ում"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB լրասարք"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"Միշտ բացել <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը, երբ <xliff:g id="USB_DEVICE">%2$s</xliff:g> լրասարքը միացված է"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Միշտ բացել <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը, երբ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> լրասարքը միացված է"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"Թույլատրե՞լ USB-ով վրիպազերծումը"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"Համակարգչի RSA-ի բանալի մատնահետքն է`\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"RSA բանալու թվային մատնահետք`\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Միշտ թույլատրել այս համակարգչից"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"Թույլատրել"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB-ով վրիպազերծումը թույլատրված չէ"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Ձայնային հուշումներ"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Ապակողպել"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Մատնահետքի սպասում"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Ապակողպել չօգտագործելով մատնահետքը"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Ապակողպել առանց մատնահետքի"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"Դեմքի սկանավորում"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Ուղարկել"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Կառավարել ծանուցումները"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Հաստատվեց"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Ավարտելու համար հպեք «Հաստատել»"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Նույնականացված է"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Օգտագործել PIN կոդ"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Օգտագործել նախշ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Օգտագործել գաղտնաբառ"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN կոդը սխալ է"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Նախշը սխալ է"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Գաղտնաբառը սխալ է"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Չափից շատ սխալ փորձ է կատարվել:\nՆորից փորձեք <xliff:g id="NUMBER">%d</xliff:g> վայրկյանից:"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Հպեք մատնահետքի սկաներին"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Մատնահետքի պատկերակ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Դեմքի ճանաչում…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ծանուցումներ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Լապտեր"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Օգտագործվում է տեսախցիկը"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Բջջային ինտերնետ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Տվյալների օգտագործումը"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Մնացած տվյալները"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 0b3ef70..d0b1045 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Menyiapkan metode masukan"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Keyboard fisik"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Izinkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Izinkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAplikasi ini belum diberi izin merekam, tetapi dapat merekam audio melalui perangkat USB ini."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Izinkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk menangani <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk menangani <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAplikasi ini belum diberi izin merekam, tetapi dapat merekam audio melalui perangkat USB ini."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk menangani <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Tidak ada apl terpasang yang bekerja dengan aksesori USB ini. Pelajari lebih lanjut tentang aksesori ini di <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Aksesori USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Dikonfirmasi"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Ketuk Konfirmasi untuk menyelesaikan"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Diautentikasi"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Gunakan PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Gunakan pola"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Gunakan sandi"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN salah"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Pola salah"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Sandi salah"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Terlalu banyak kesalahan pola.\nCoba lagi dalam <xliff:g id="NUMBER">%d</xliff:g> detik."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Sentuh sensor sidik jari"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon sidik jari"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Mencari wajah Anda…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifikasi"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampu senter"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera sedang digunakan"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Data seluler"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Penggunaan kuota"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Data tersisa"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 7a8d290..8985d27 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Setja upp innsláttaraðferðir"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Vélbúnaðarlyklaborð"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Viltu veita <xliff:g id="APPLICATION">%1$s</xliff:g> aðgang að <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Viltu veita <xliff:g id="APPLICATION">%1$s</xliff:g> aðgang að <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nÞetta forrit hefur ekki fengið heimild fyrir upptöku en gæti tekið upp hljóð í gegnum þetta USB-tæki."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Viltu veita <xliff:g id="APPLICATION">%1$s</xliff:g> aðgang að <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Viltu opna <xliff:g id="APPLICATION">%1$s</xliff:g> til að sjá um <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Viltu opna <xliff:g id="APPLICATION">%1$s</xliff:g> til að vinna með <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nÞetta forrit hefur ekki fengið heimild fyrir upptöku en gæti tekið upp hljóð í gegnum þetta USB-tæki."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Viltu opna <xliff:g id="APPLICATION">%1$s</xliff:g> til að sjá um <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Engin uppsett forrit virka með þessum USB-aukabúnaði. Frekari upplýsingar eru á <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-aukabúnaður"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Staðfest"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Ýttu á „Staðfesta“ til að ljúka"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Auðkennt"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Nota PIN-númer"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Nota mynstur"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Nota aðgangsorð"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Rangt PIN-númer"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Rangt mynstur"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Rangt aðgangsorð"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Of margar misheppnaðar tilraunir.\nReyndu aftur eftir <xliff:g id="NUMBER">%d</xliff:g> sekúndur."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Snertu fingrafaralesarann"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingrafaratákn"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Leitar að þér ..."</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Tilkynningar"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Vasaljós"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Myndavél í notkun"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Farsímagögn"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Gagnanotkun"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Gögn eftir"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index cc053be..68169ab 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configura metodi di immissione"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Tastiera fisica"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Consentire a <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vuoi consentire all\'app <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nA questa app non è stata concessa l\'autorizzazione di registrazione, ma l\'app potrebbe acquisire l\'audio tramite questo dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Consentire a <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vuoi aprire <xliff:g id="APPLICATION">%1$s</xliff:g> per gestire <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Vuoi aprire <xliff:g id="APPLICATION">%1$s</xliff:g> per gestire <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nA questa app non è stata concessa l\'autorizzazione di registrazione, ma l\'app potrebbe acquisire l\'audio tramite questo dispositivo USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vuoi aprire <xliff:g id="APPLICATION">%1$s</xliff:g> per gestire <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Nessuna app installata funziona con questo accessorio USB. Altre info su <xliff:g id="URL">%1$s</xliff:g>."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accessorio USB"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"Apri sempre <xliff:g id="APPLICATION">%1$s</xliff:g> quando si collega <xliff:g id="USB_DEVICE">%2$s</xliff:g>"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Apri sempre <xliff:g id="APPLICATION">%1$s</xliff:g> quando si collega <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"Consentire debug USB?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"Impronta della chiave RSA del computer: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Fingerprint della chiave RSA del computer: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Consenti sempre da questo computer"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"Consenti"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Debug USB non consentito"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confermato"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tocca Conferma per completare"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticazione eseguita"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Utilizza PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Usa sequenza"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Utilizza password"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN errato"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Sequenza errata"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Password errata"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Troppi tentativi errati.\nRiprova tra <xliff:g id="NUMBER">%d</xliff:g> secondi."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Tocca il sensore di impronte"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icona dell\'impronta"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"In attesa del volto…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifiche"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Torcia"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Fotocamera in uso"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dati mobili"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Utilizzo dati"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dati rimanenti"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 09e4f0e..d059489 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"הגדר שיטות קלט"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"מקלדת פיזית"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"האם לתת לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> גישה אל <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"‏האם לאפשר לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> גישה אל <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nאפליקציה זו לא קיבלה הרשאה להקליט אך יכולה לתעד אודיו באמצעות מכשיר USB זה."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"האם לתת לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> גישה אל <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"האם לפתוח את <xliff:g id="APPLICATION">%1$s</xliff:g> כדי לעבוד עם <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"האם לפתוח את <xliff:g id="APPLICATION">%1$s</xliff:g> כדי לעבוד עם <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"‏אין אפליקציות מותקנות הפועלות עם אביזר ה-USB. למידע נוסף על אביזר זה היכנס לכתובת <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"‏אביזר USB"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"מאושר"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"יש להקיש על \'אישור\' לסיום"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"מאומת"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"שימוש בקוד אימות"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"שימוש בקו ביטול נעילה"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"שימוש בסיסמה"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"קוד אימות שגוי"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"קו ביטול נעילה שגוי"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"סיסמה שגויה"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"יותר מדי ניסיונות שגויים.\nיש לנסות שוב בעוד <xliff:g id="NUMBER">%d</xliff:g> שניות."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"יש לגעת בחיישן טביעות האצבע"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"סמל טביעת אצבע"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"מחפש אותך…"</string>
@@ -384,8 +378,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"התראות"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"פנס"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"מצלמה בשימוש"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"חבילת גלישה"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"שימוש בנתונים"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"מכסת נתונים נותרת"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 3dc9fb7..e89ae5b 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"入力方法をセットアップ"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"物理キーボード"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> に <xliff:g id="USB_DEVICE">%2$s</xliff:g> へのアクセスを許可しますか?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> に <xliff:g id="USB_DEVICE">%2$s</xliff:g>へのアクセスを許可しますか?\nこのアプリに録音権限は付与されていませんが、アクセスを許可すると、この USB デバイスから音声を収集できるようになります。"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> に <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> へのアクセスを許可しますか?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="APPLICATION">%1$s</xliff:g> を起動して <xliff:g id="USB_DEVICE">%2$s</xliff:g> を処理しますか?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> を開いて <xliff:g id="USB_DEVICE">%2$s</xliff:g>を利用しますか?\nこのアプリに録音権限は付与されていませんが、この USB デバイスから音声を収集できるようになります。"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="APPLICATION">%1$s</xliff:g> を起動して <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> を処理しますか?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"このUSBアクセサリを扱うアプリはインストールされていません。詳細: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USBアクセサリ"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"確認しました"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"完了するには [確認] をタップしてください"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"認証済み"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN を使用"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"パターンを使用"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"パスワードを使用"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN が正しくありません"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"パターンが正しくありません"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"パスワードが正しくありません"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"間違えた回数が上限を超えました。\n<xliff:g id="NUMBER">%d</xliff:g> 秒後にもう一度お試しください。"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"指紋認証センサーをタップしてください"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"指紋アイコン"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"顔を認証しています…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ライト"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"カメラを使用中"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"モバイルデータ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"データ使用量"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"残りのデータ"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 24db256..50006dd 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"შეყვანის მეთოდების დაყენება"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ფიზიკური კლავიატურა"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"მიეცეს <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ზე წვდომის უფლება?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"დართავთ <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ზე წვდომის ნებას?\nამ აპს არ აქვს მინიჭებული ჩაწერის ნებართვა, მაგრამ შეუძლია ჩაიწეროს აუდიო ამ USB მოწყობილობის მეშვეობით."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"მიეცეს <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>-ზე წვდომის უფლება?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"გსურთ, გახსნათ <xliff:g id="APPLICATION">%1$s</xliff:g>, <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ის გამოსაყენებლად?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"გახსნით <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ის გამოსაყენებლად?\nამ აპს არ აქვს მინიჭებული ჩაწერის ნებართვა, მაგრამ შეუძლია ჩაიწეროს აუდიო ამ USB მოწყობილობის მეშვეობით."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"გსურთ, გახსნათ <xliff:g id="APPLICATION">%1$s</xliff:g>, <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>-ის გამოსაყენებლად?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"არცერთი დაყენებული აპი არ მუშაობს ამ USB აქსესუართან. შეიტყვეთ მეტი ამ აქსესუარის შესახებ <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB აქსესუარი"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"დადასტურებული"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"დასასრულებლად შეეხეთ „დადასტურებას“"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ავტორიზებულია"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN-კოდის გამოყენება"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ნიმუშის გამოყენება"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"პაროლის გამოყენება"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN-კოდი არასწორია"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ნიმუში არასწორია"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"პაროლი არასწორია"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"დაფიქსირდა ძალიან ბევრი არასწორი მცდელობა.\nცადეთ ხელახლა <xliff:g id="NUMBER">%d</xliff:g> წამში."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"შეეხეთ თითის ანაბეჭდის სენსორს"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"თითის ანაბეჭდის ხატულა"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"მიმდინარეობს თქვენი ძიება…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"შეტყობინებები"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ფანარი"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"კამერა გამოიყენება"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"მობილური ინტერნეტი"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"მონაცემთა მოხმარება"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"დარჩენილი მონაცემები"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index ff1b9fc..05e521c 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Енгізу әдістерін орнату"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Физикалық пернетақта"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына <xliff:g id="USB_DEVICE">%2$s</xliff:g> құрылғысына кіруге рұқсат берілсін бе?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына <xliff:g id="USB_DEVICE">%2$s</xliff:g> құрылғысын пайдалануға рұқсат етілсін бе?\nҚолданбаның жазу рұқсаты жоқ, бірақ осы USB құрылғысы арқылы аудио жаза алады."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> жабдығына кіруге рұқсат берілсін бе?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> жабдығын басқару үшін <xliff:g id="APPLICATION">%1$s</xliff:g> ашылсын ба?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> құрылғысын пайдалану үшін <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасын ашу керек пе?\nҚолданбаға жазу рұқсаты берілмеді, бірақ ол осы USB құрылғысы арқылы дыбыс жаза алады."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> жабдығын басқару үшін <xliff:g id="APPLICATION">%1$s</xliff:g> ашылсын ба?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Орнатылған қолданбалар осы USB жабдығымен жұмыс жасамайды.Жабдықты <xliff:g id="URL">%1$s</xliff:g> ден қараңыз."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB жабдығы"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Расталды"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Аяқтау үшін \"Растау\" түймесін түртіңіз."</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Аутентификацияланған"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN кодын пайдалану"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Өрнекті пайдалану"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Құпия сөзді пайдалану"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN коды қате."</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Өрнек қате."</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Құпия сөз қате."</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Тым көп қате енгізілді.\n<xliff:g id="NUMBER">%d</xliff:g> секундта әрекетті қайталаңыз."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Саусақ ізін оқу сканерін түртіңіз"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Саусақ ізі белгішесі"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Бет ізделуде…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Хабарландырулар"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Қалта шам"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Камера қолданылып жатыр"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобильдік деректер"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Дерек шығыны"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Қалған деректер"</string>
@@ -856,7 +848,7 @@
     <string name="pip_phone_settings" msgid="8080777499521528521">"Реттеулер"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Жабу үшін төмен қарай сүйреңіз"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Mәзір"</string>
-    <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> \"сурет ішіндегі сурет\" режимінде"</string>
+    <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> \"суреттегі сурет\" режимінде"</string>
     <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> деген пайдаланушының бұл мүмкіндікті пайдалануын қаламасаңыз, параметрлерді түртіп ашыңыз да, оларды өшіріңіз."</string>
     <string name="pip_play" msgid="1417176722760265888">"Ойнату"</string>
     <string name="pip_pause" msgid="8881063404466476571">"Кідірту"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 323138c..a628383 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"រៀបចំ​វិធីសាស្ត្រ​បញ្ចូល"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ក្ដារ​ចុច​ពិតប្រាកដ"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"អនុញ្ញាត <xliff:g id="APPLICATION">%1$s</xliff:g> ឱ្យចូលប្រើ <xliff:g id="USB_DEVICE">%2$s</xliff:g> មែនទេ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"អនុញ្ញាតឱ្យ <xliff:g id="APPLICATION">%1$s</xliff:g> ចូលប្រើ <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nកម្មវិធីនេះ​មិនទាន់បាន​ទទួលសិទ្ធិ​ថតសំឡេងនៅឡើយទេ ប៉ុន្តែ​អាចថត​សំឡេង​តាមរយៈ​ឧបករណ៍ USB នេះបាន។"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"អនុញ្ញាត <xliff:g id="APPLICATION">%1$s</xliff:g> ឱ្យចូលប្រើ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> មែនទេ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"បើក <xliff:g id="APPLICATION">%1$s</xliff:g> ដើម្បីគ្រប់គ្រង <xliff:g id="USB_DEVICE">%2$s</xliff:g> មែនទេ?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"បើក <xliff:g id="APPLICATION">%1$s</xliff:g> ដើម្បីគ្រប់គ្រង <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nកម្មវិធីនេះ​មិនទាន់បាន​ទទួលសិទ្ធិ​ថតសំឡេង​នៅឡើយទេ ប៉ុន្តែអាច​ថតសំឡេង​តាមរយៈ​ឧបករណ៍ USB នេះ។"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"បើក <xliff:g id="APPLICATION">%1$s</xliff:g> ដើម្បីគ្រប់គ្រង <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> មែនទេ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"គ្មាន​កម្មវិធី​បាន​ដំឡើង​ដំណើរការ​ជា​មួយ​ឧបករណ៍​យូអេសប៊ី។ ស្វែងយល់​បន្ថែម​អំពី​ឧបករណ៍​នេះ​នៅ <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"ឧបករណ៍​យូអេសប៊ី"</string>
@@ -128,22 +128,15 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"បានបញ្ជាក់"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"ចុច \"បញ្ជាក់\" ដើម្បីបញ្ចប់"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"បាន​ផ្ទៀងផ្ទាត់"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ប្រើកូដ PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ប្រើ​លំនាំ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"ប្រើពាក្យសម្ងាត់"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"កូដ PIN មិន​ត្រឹមត្រូវ​"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"លំនាំមិនត្រឹមត្រូវ"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ពាក្យសម្ងាត់មិនត្រឹមត្រូវ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ការព្យាយាម​ចូលខុស​ច្រើនដងពេក។\nសូមព្យាយាម​ម្តងទៀត​ក្នុងរយៈពេល <xliff:g id="NUMBER">%d</xliff:g> វិនាទី។"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ប៉ះ​ឧបករណ៍​ចាប់ស្នាម​ម្រាមដៃ"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"រូបតំណាង​ស្នាម​ម្រាមដៃ"</string>
+    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"រូប​ស្នាម​ម្រាមដៃ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"កំពុងស្វែងរកអ្នក…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"រូប​ផ្ទៃមុខ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ប៊ូតុង​ពង្រីក​ត្រូវ​គ្នា។"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ការ​ជូនដំណឹង"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ពិល"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"កំពុងប្រើ​កាមេរ៉ា"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ទិន្នន័យ​ទូរសព្ទចល័ត"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ការ​ប្រើ​ទិន្នន័យ"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ទិន្នន័យ​នៅសល់"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index ac593e8..dc4674a 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ಇನ್‌ಪುಟ್ ವಿಧಾನಗಳನ್ನು ಹೊಂದಿಸು"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಪ್ರವೇಶಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಅನ್ನು ಪ್ರವೇಶಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?\nಈ ಆ್ಯಪ್‌ಗೆ ರೆಕಾರ್ಡ್ ಅನುಮತಿಯನ್ನು ನೀಡಲಾಗಿಲ್ಲ, ಆದರೆ ಈ USB ಸಾಧನದ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಸೆರೆಹಿಡಿಯಬಹುದು."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ಗೆ ಪ್ರವೇಶಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಅನ್ನು ನಿಯಂತ್ರಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?\nಈ ಆ್ಯಪ್‌ಗೆ ರೆಕಾರ್ಡ್ ಅನುಮತಿಯನ್ನು ನೀಡಲಾಗಿಲ್ಲ, ಆದರೆ ಈ USB ಸಾಧನದ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಸೆರೆಹಿಡಿಯಬಹುದು."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ಆಪ್‌ಗಳು USB ಪರಿಕರದಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುವುದಿಲ್ಲ. ಆ ಬಗ್ಗೆ <xliff:g id="URL">%1$s</xliff:g> ನಲ್ಲಿ ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB ಪರಿಕರ"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಸಂಪರ್ಕಗೊಂಡಾಗ ಯಾವಾಗಲೂ <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ಸಂಪರ್ಕಗೊಂಡಾಗ ಯಾವಾಗಲೂ <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"ಕಂಪ್ಯೂಟರ್‌ನ RSA ಕೀ ಫಿಂಗರ್ ಪ್ರಿಂಟ್ ಹೀಗಿದೆ :\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"ಕಂಪ್ಯೂಟರ್‌ನ RSA ಕೀ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಹೀಗಿದೆ :\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"ಈ ಕಂಪ್ಯೂಟರ್‌ನಿಂದ ಯಾವಾಗಲೂ ಅನುಮತಿಸಿ"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"ಅನುಮತಿಸಿ"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ಅನುಮತಿಸಲಾಗಿಲ್ಲ"</string>
@@ -110,8 +110,8 @@
     <string name="accessibility_phone_button" msgid="6738112589538563574">"ಫೋನ್"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"ಧ್ವನಿ ಸಹಾಯಕ"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"ಅನ್‌ಲಾಕ್"</string>
-    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"ಫಿಂಗರ್ ಪ್ರಿಂಟ್ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"ನಿಮ್ಮ ಬೆರಳಚ್ಚು ಬಳಸದೆಯೇ ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
+    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್‍‍ಗಾಗಿ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"ನಿಮ್ಮ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಬಳಸದೆಯೇ ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"ಮುಖವನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"ಕಳುಹಿಸಿ"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿರ್ವಹಿಸಿ"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"ಪೂರ್ಣಗೊಳಿಸಲು ದೃಢೀಕರಿಸಿ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ಪಿನ್ ಬಳಸಿ"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ಪ್ಯಾಟರ್ನ್ ಬಳಸಿ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"ಪಾಸ್‌ವರ್ಡ್ ಬಳಸಿ"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ತಪ್ಪಾದ ಪಿನ್‌"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ಪ್ಯಾಟರ್ನ್ ತಪ್ಪಾಗಿದೆ"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ಪಾಸ್‌ವರ್ಡ್ ತಪ್ಪಾಗಿದೆ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ಹಲವಾರು ತಪ್ಪು ಪ್ರಯತ್ನಗಳು.\nಮತ್ತೆ <xliff:g id="NUMBER">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌‌ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಐಕಾನ್"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ನಿಮಗಾಗಿ ಹುಡುಕಲಾಗುತ್ತಿದೆ…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ಅಧಿಸೂಚನೆಗಳು"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ಫ್ಲಾಶ್‌ಲೈಟ್‌"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ಕ್ಯಾಮರಾ ಬಳಕೆಯಲ್ಲಿದೆ"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ಮೊಬೈಲ್ ಡೇಟಾ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ಡೇಟಾ ಬಳಕೆ"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ಉಳಿದಿರುವ ಡೇಟಾ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index f37ec00..714af0c 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"입력 방법 설정"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"물리적 키보드"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱이 <xliff:g id="USB_DEVICE">%2$s</xliff:g>에 액세스하도록 허용하시겠습니까?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g>에서 <xliff:g id="USB_DEVICE">%2$s</xliff:g>에 액세스하도록 허용하시겠습니까?\n이 앱에는 녹음 권한이 부여되지 않았지만, 이 USB 기기를 통해 오디오를 녹음할 수 있습니다."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱이 <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>에 액세스하도록 허용하시겠습니까?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱을 열어 <xliff:g id="USB_DEVICE">%2$s</xliff:g>을(를) 처리하시겠습니까?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>을(를) 처리하기 위해 <xliff:g id="APPLICATION">%1$s</xliff:g>을(를) 여시겠습니까?\n이 앱에는 녹음 권한이 부여되지 않았지만, 이 USB 기기를 통해 오디오를 녹음할 수 있습니다."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱을 열어 <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>을(를) 처리하시겠습니까?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"이 USB와 호환되는 설치 앱이 없습니다. <xliff:g id="URL">%1$s</xliff:g>에서 세부정보를 참조하세요."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB 액세서리"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"음성 지원"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"잠금 해제"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"지문 대기 중"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"지문 파일을 사용하지 않고 잠금 해제"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"지문을 사용하지 않고 잠금 해제"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"얼굴 스캔 중"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"보내기"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"알림 관리"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"확인함"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"완료하려면 확인을 탭하세요."</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"인증됨"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN 사용"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"패턴 사용"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"비밀번호 사용"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"잘못된 PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"잘못된 패턴"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"잘못된 비밀번호"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"잘못된 시도 횟수가 너무 많습니다.\n<xliff:g id="NUMBER">%d</xliff:g>초 후에 다시 시도하세요."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"지문 센서를 터치하세요."</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"지문 아이콘"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"찾는 중..."</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"알림"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"손전등"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"카메라 사용 중"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"모바일 데이터"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"데이터 사용"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"잔여 데이터"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index beb2b02..820c6b3 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Киргизүү ыкмасын тууралоо"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Аппараттык тергич"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу <xliff:g id="USB_DEVICE">%2$s</xliff:g> түзмөгүн колдоно берсинби?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу үчүн <xliff:g id="USB_DEVICE">%2$s</xliff:g> түзмөгүнө мүмкүнчүлүк алууга уруксат бересизби?\nБул колдонмонун жаздырууга уруксаты жок, бирок бул USB түзмөгү аркылуу аудиону жаздыра алат."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> кабелин колдоно берсинби?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> түзмөгүнө туташуу үчүн <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу ачылсынбы?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> кабелине туташуу үчүн <xliff:g id="APPLICATION">%1$s</xliff:g> ачылсынбы?\nБул колдонмонун жаздырууга уруксаты жок, бирок бул USB түзмөгү аркылуу аудиону жаздыра алат."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> кабелине туташуу үчүн <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу ачылсынбы?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Эч бир орнотулган колдонмо USB аксессуар м-н иштебейт. Кенен маалыматтар: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB шайманы"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Ырасталды"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Бүтүрүү үчүн \"Ырастоо\" баскычын басыңыз"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Аныктыгы текшерилди"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN кодду колдонуу"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Графикалык ачкычты колдонуу"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Сырсөз колдонуу"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN код туура эмес"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Графикалык ачкыч туура эмес"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Сырсөз туура эмес"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Өтө көп жолу туура эмес аракет кылынды.\n<xliff:g id="NUMBER">%d</xliff:g> секунддан кийин кайра кайталаңыз."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Манжа изинин сенсорун басыңыз"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Манжа изинин сүрөтчөсү"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Жүзүңүз изделүүдө…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Билдирмелер"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Кол чырак"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Камера колдонулууда"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобилдик Интернет"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Дайындардын өткөрүлүшү"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Калган дайындар"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 68c9951..89d3779 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ຕັ້ງຄ່າວິທີການປ້ອນຂໍ້ມູນ"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ແປ້ນພິມແທ້"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"ອະນຸຍາດໃຫ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ໄດ້ບໍ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"ອະນຸຍາດໃຫ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ໄດ້ບໍ?\nແອັບນີ້ບໍ່ໄດ້ຮັບອະນຸາດໃຫ້ບັນທຶກໄດ້ແຕ່ສາມາດບັນທຶກສຽງໄດ້ຜ່ານອຸປະກອນ USB ນີ້."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"ອະນຸຍາດໃຫ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ໄດ້ບໍ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"ເປີດ <xliff:g id="APPLICATION">%1$s</xliff:g> ເພື່ອໃຊ້ກັບ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ບໍ?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"ເປີດ <xliff:g id="APPLICATION">%1$s</xliff:g> ເພື່ອໃຊ້ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ບໍ?\nແອັບນີ້ຍັງບໍ່ໄດ້ຮັບອະນຸຍາດໃຫ້ບັນທຶກເທື່ອ ແຕ່ສາມາດບັນທຶກສຽງຜ່ານອຸປະກອນ USB ນີ້ໄດ້."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"ເປີດ <xliff:g id="APPLICATION">%1$s</xliff:g> ເພື່ອໃຊ້ກັບ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ບໍ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ບໍ່ມີແອັບຯໃດທີ່ຕິດຕັ້ງໄປແລ້ວ ສາມາດເຮັດວຽກຮ່ວມກັບອຸປະກອນເສີມ USB ນີ້ໄດ້. ສຶກສາເພີ່ມເຕີມກ່ຽວກັບອຸປະກອນເສີມນີ້ທີ່ <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"ອຸປະກອນເສີມ USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"ຢືນຢັນແລ້ວ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"ແຕະຢືນຢັນເພື່ອສຳເລັດ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ຮັບຮອງຄວາມຖືກຕ້ອງແລ້ວ"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ໃຊ້ PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ໃຊ້ຮູບແບບ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"ໃຊ້ລະຫັດຜ່ານ"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN ບໍ່ຖືກຕ້ອງ"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ຮູບແບບບໍ່ຖືກຕ້ອງ"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ລະຫັດຜ່ານບໍ່ຖືກຕ້ອງ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ມີ​ຄວາມ​ພະ​ຍາ​ຍາມ​ບໍ່​ຖືກ​ຕ້ອງ​ຫຼາຍ​ເທື່ອ​ເກີນ​ໄປ.\nກະລຸນາລອງ​ໃໝ່​ອີກ​ໃນ <xliff:g id="NUMBER">%d</xliff:g> ​ວິ​ນາ​ທີ."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ແຕະໃສ່ເຊັນເຊີລາຍນິ້ວມື"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ໄອຄອນລາຍນິ້ວມື"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ກຳລັງຊອກຫາທ່ານ…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ການແຈ້ງເຕືອນ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"​ໄຟ​ສາຍ"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ມີການໃຊ້ກ້ອງຖ່າຍຮູບຢູ່"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ອິນເຕີເນັດມືຖື"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"​ການ​​ນຳ​ໃຊ້​​ຂໍ້​ມູນ"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"​ຂໍ້​ມູນ​ທີ່​ຍັງ​ເຫຼືອ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 230194d..208f49b 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nustatyti įvesties metodus"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizinė klaviatūra"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Leisti „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti įrenginį (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Leisti „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti įrenginį (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?\nŠiai programai nebuvo suteiktas leidimas įrašyti, bet ji gali užfiksuoti garsą per šį USB įrenginį."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Leisti „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti įrenginį (<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>)?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Atidaryti „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kad būtų galima tvarkyti įrenginį (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Atidaryti programą „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kad ji galėtų tvarkyti „<xliff:g id="USB_DEVICE">%2$s</xliff:g>“?\nŠiai programai nebuvo suteiktas leidimas įrašyti, bet ji gali užfiksuoti garsą per šį USB įrenginį."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Atidaryti „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kad būtų galima tvarkyti įrenginį (<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>)?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Su šiuo USB priedu neveiks jokios įdieg. pr. Suž. daugiau apie šį priedą adresu <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB reikmuo"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Patvirtinta"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Paliesk. „Patvirtinti“, kad užbaigtumėte"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentifikuota"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Naudoti PIN kodą"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Naudoti atrakinimo piešinį"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Naudoti slaptažodį"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Netinkamas PIN kodas"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Netinkamas atrakinimo piešinys"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Netinkamas slaptažodis"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Per daug klaidingų bandymų.\nBandykite dar kartą po <xliff:g id="NUMBER">%d</xliff:g> sek."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Palieskite piršto antspaudo jutiklį"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Piršto antspaudo piktograma"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Ieškoma jūsų…"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pranešimai"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Žibintuvėlis"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Fotoaparatas naudojamas"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiliojo ryšio duomenys"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Duomenų naudojimas"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Likę duomenys"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index e1905f5..a96fc3b 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Iestatīt ievades metodes"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fiziskā tastatūra"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Vai atļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt šai ierīcei: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vai atļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt ierīcei “<xliff:g id="USB_DEVICE">%2$s</xliff:g>”?\nŠai lietotnei nav piešķirta ierakstīšanas atļauja, taču tā varētu tvert audio, izmantojot šo USB ierīci."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Vai atļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt šim piederumam: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vai atvērt lietotni <xliff:g id="APPLICATION">%1$s</xliff:g>, lai izmantotu šo ierīci: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Vai vēlaties atvērt lietotni <xliff:g id="APPLICATION">%1$s</xliff:g>, lai pārvaldītu ierīci <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nŠai lietotnei nav piešķirta ierakstīšanas atļauja, taču tā varētu tvert audio, izmantojot šo USB ierīci."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vai atvērt lietotni <xliff:g id="APPLICATION">%1$s</xliff:g>, lai izmantotu šo piederumu: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Neviena no inst. liet. nedarb. ar šo USB pied. Uzz. vairāk par šo pied. vietnē <xliff:g id="URL">%1$s</xliff:g>."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB piederums"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Apstiprināts"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Lai pabeigtu, pieskarieties Apstiprināt"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentifikācija veikta"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Izmantot PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Izmantot kombināciju"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Izmantot paroli"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Nepareizs PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Nepareiza kombinācija"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Nepareiza parole"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Pārāk daudz neveiksmīgu mēģinājumu.\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER">%d</xliff:g> sekundēm."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Pieskarieties pirksta nospieduma sensoram"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Pirksta nospieduma ikona"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Notiek jūsu sejas meklēšana…"</string>
@@ -382,8 +375,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Paziņojumi"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Zibspuldze"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera tiek lietota"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilie dati"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datu lietojums"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Atlikušie dati"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 300dff5..f8dea79 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Постави методи на внес."</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Физичка тастатура"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Ќе дозволите <xliff:g id="APPLICATION">%1$s</xliff:g> да пристапува до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Дали дозволувате <xliff:g id="APPLICATION">%1$s</xliff:g> да пристапи до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nНа апликацијава не ѝ е доделена дозвола за снимање, но може да снима аудио преку овој USB-уред."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Ќе дозволите <xliff:g id="APPLICATION">%1$s</xliff:g> да пристапува до <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Да се отвори <xliff:g id="APPLICATION">%1$s</xliff:g> за да управува со <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Да се отвори ли <xliff:g id="APPLICATION">%1$s</xliff:g> за да се управува со <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nНа апликацијава не ѝ е доделена дозвола за снимање, но може да снима аудио преку овој USB-уред."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Да се отвори <xliff:g id="APPLICATION">%1$s</xliff:g> за да управува со <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Нема инсталирано апликации што работат со овој USB додаток. Дознајте повеќе за овој додаток на <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB додаток"</string>
@@ -128,22 +128,15 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Потврдено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Допрете „Потврди“ за да се заврши"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Проверена"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Користи PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Користи шема"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Користи лозинка"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Погрешен PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Погрешна шема"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Погрешна лозинка"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Премногу погрешни обиди.\nОбидете се повторно за <xliff:g id="NUMBER">%d</xliff:g>секунди."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Допрете го сензорот за отпечатоци"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Икона за отпечатоци"</string>
+    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Икона за отпечаток"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Ве бараме вас…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Икона за лице"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Копче за компатибилност на зум."</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Известувања"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Светилка"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Камерата е во употреба"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобилен интернет"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Потрошен интернет"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Преостанати податоци"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 0a06b2c..66265cb 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ടൈപ്പുചെയ്യൽ രീതികൾ സജ്ജീകരിക്കുക"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ഫിസിക്കൽ കീബോഡ്"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ആക്‌സസ് ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g>-നെ അനുവദിക്കണോ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ആക്‌സസ് ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g> എന്നതിനെ അനുവദിക്കണോ?\nഈ ആപ്പിന് റെക്കോർഡ് അനുമതി നൽകിയിട്ടില്ല, എന്നാൽ ഈ USB ഉപകരണത്തിലൂടെ ഓഡിയോ ക്യാപ്‌ചർ ചെയ്യാനാവും."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ആക്‌സസ് ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g>-നെ അനുവദിക്കണോ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> കൈകാര്യം ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g> തുറക്കണോ?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> കൈകാര്യം ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g> തുറക്കണോ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ഈ USB ആക്‌സസ്സറിയിൽ ഇൻസ്‌റ്റാളുചെയ്‌തവയൊന്നും പ്രവർത്തിക്കുന്നില്ല. <xliff:g id="URL">%1$s</xliff:g>-ൽ ഇതേക്കുറിച്ച് കൂടുതലറിയുക"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB ആക്‌സസ്സറി"</string>
@@ -110,7 +111,7 @@
     <string name="accessibility_phone_button" msgid="6738112589538563574">"ഫോണ്‍"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"വോയ്‌സ് സഹായം"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"അണ്‍ലോക്ക് ചെയ്യുക"</string>
-    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"ഫിംഗർപ്രിന്റിനായി കാക്കുന്നു"</string>
+    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"ഫിംഗർപ്രിന്റിനായി കാത്തിരിക്കുന്നു"</string>
     <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കാതെ അൺലോക്കുചെയ്യുക"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"മുഖം സ്കാൻ ചെയ്യുന്നു"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"അയയ്ക്കുക"</string>
@@ -128,22 +129,15 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"സ്ഥിരീകരിച്ചു"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"പൂർത്തിയാക്കാൻ സ്ഥിരീകരിക്കുക ടാപ്പ് ചെയ്യൂ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"പരിശോധിച്ചുറപ്പിച്ചു"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
-    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"വിരലടയാള സെൻസർ സ്‌പർശിക്കുക"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"വിരലടയാള ഐക്കൺ"</string>
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"പിൻ ഉപയോഗിക്കുക"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"പാറ്റേൺ ഉപയോഗിക്കുക"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"പാസ്‌വേഡ് ഉപയോഗിക്കുക"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"പിൻ തെറ്റാണ്"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"പാറ്റേൺ തെറ്റാണ്"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"പാസ്‌വേഡ് തെറ്റാണ്"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"നിരവധി തെറ്റായ ശ്രമങ്ങൾ. \n<xliff:g id="NUMBER">%d</xliff:g> സെക്കൻഡിൽ വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ഫിംഗർപ്രിന്റ് സെൻസർ സ്‌പർശിക്കുക"</string>
+    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ഫിംഗർപ്രിന്റ് ഐക്കൺ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"നിങ്ങൾക്കായി തിരയുന്നു…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"മുഖത്തിന്റെ ഐക്കൺ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"അനുയോജ്യതാ സൂം ബട്ടൺ."</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"അറിയിപ്പുകൾ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ടോർച്ച്"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ക്യാമറ ഉപയോഗത്തിലാണ്"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"മൊബൈൽ ഡാറ്റ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ഡാറ്റാ ഉപയോഗം"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ശേഷിക്കുന്ന ഡാറ്റ"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 0298d20..00e6dcb 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Оруулах аргыг тохируулах"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Бодит гар"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g>-г <xliff:g id="USB_DEVICE">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g>-д <xliff:g id="USB_DEVICE">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?\nЭнэ аппад бичих зөвшөөрөл олгогдоогүй ч USB төхөөрөмжөөр дамжуулан аудио бичиж чадсан."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g>-г <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>-г зохицуулахын тулд <xliff:g id="APPLICATION">%1$s</xliff:g>-г нээх үү?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>-г зохицуулахын тулд <xliff:g id="APPLICATION">%1$s</xliff:g>-г нээх үү?\nЭнэ апликейшнд бичих зөвшөөрөл олгогдоогүй ч энэ USB төхөөрөмжөөр дамжуулан аудио бичиж чадсан."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>-г зохицуулахын тулд <xliff:g id="APPLICATION">%1$s</xliff:g>-г нээх үү?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Энэ USB хэрэгсэл дээр суулгасан апп ажиллаагүй байна. Энэ хэрэгслийн талаар <xliff:g id="URL">%1$s</xliff:g>-с дэлгэрэнгүй үзнэ үү."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB төхөөрөмж"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Баталгаажсан"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Дуусгахын тулд баталгаажуулахыг товших"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Баталгаажуулагдсан"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ПИН ашиглах"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Хээ ашиглах"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Нууц үг ашиглах"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ПИН код буруу байна"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Хээ буруу байна"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Нууц үг буруу байна"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Хэт олон удаа буруу оруулсан байна.\n<xliff:g id="NUMBER">%d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Хурууны хээ мэдрэгчид хүрэх"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Хурууны хээний дүрс тэмдэг"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Таныг хайж байна…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Мэдэгдэл"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Гар чийдэн"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Камерыг ашиглаж байна"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобайл дата"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Дата ашиглалт"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Үлдсэн дата"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 07b985f..671060b 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"इनपुट पद्धती सेट करा"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"वास्तविक कीबोर्ड"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> ला <xliff:g id="USB_DEVICE">%2$s</xliff:g> अ‍ॅक्सेस करण्याची अनुमती द्यायची का?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> ला <xliff:g id="USB_DEVICE">%2$s</xliff:g> अ‍ॅक्सेस करण्याची अनुमती द्यायची का?\nया अ‍ॅपला रेकॉर्ड करण्याची परवानगी दिलेली नाही पण या USB डिव्हाइसद्वारे ऑडिओ कॅप्चर केला जाऊ शकतो."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> ला <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> अ‍ॅक्सेस करण्याची अनुमती द्यायची का?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> हाताळण्यासाठी <xliff:g id="APPLICATION">%1$s</xliff:g> उघडायचे का?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> हाताळण्यासाठी <xliff:g id="APPLICATION">%1$s</xliff:g> उघडायचे का?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"इंस्टॉल केलेली अ‍ॅप्स या USB उपसाधनासह कार्य करत नाहीत. <xliff:g id="URL">%1$s</xliff:g> येथे या उपसाधनाविषयी अधिक जाणून घ्या"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB उपसाधन"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"निश्चित केले"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"पूर्ण करण्यासाठी खात्री करा वर टॅप करा"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ऑथेंटिकेशन केलेले"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"पिन वापरा"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"पॅटर्न वापरा"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"पासवर्ड वापरा"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"चुकीचा पिन"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"चुकीचा पॅटर्न"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"चुकीचा पासवर्ड"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"बरेच चुकीचे प्रयत्न. \n <xliff:g id="NUMBER">%d</xliff:g> सेकंदांमध्‍ये पुन्हा प्रयत्न करा."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"फिंगरप्रिंट सेन्सरला स्पर्श करा"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"फिंगरप्रिंट आयकन"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"तुमच्यासाठी शोधत आहे…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"सूचना"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"फ्लॅशलाइट"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"कॅमेरा वापरात आहे"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"मोबाइल डेटा"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"डेटा वापर"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"शिल्लक डेटा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index f696ee3..265f161 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Sediakan kaedah input"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Papan kekunci fizikal"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Benarkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Benarkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nApl ini belum diberikan kebenaran merakam tetapi dapat merakam audio melalui peranti USB ini."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Benarkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk mengendalikan <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk mengendalikan <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nApl ini belum diberikan kebenaran merakam tetapi dapat merakam audio melalui peranti USB ini."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk mengendalikan <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Tiada apl yg dipsg bfungsi dgn aksesori USB ini. Ketahui lg ttg aksesori ini di <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Aksesori USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Disahkan"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Ketik Sahkan untuk menyelesaikan"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Disahkan"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Gunakan PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Gunakan corak"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Gunakan kata laluan"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN salah"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Corak salah"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Kata laluan salah"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Terlalu banyak percubaan yang salah.\nCuba lagi dalam masa <xliff:g id="NUMBER">%d</xliff:g> saat."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Sentuh penderia cap jari"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon cap jari"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Mencari anda…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pemberitahuan"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampu suluh"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera sedang digunakan"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Data mudah alih"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Penggunaan data"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Baki data"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index eb73df7..c06bb8c 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ထည့်သွင်းနည်းများ သတ်မှတ်ခြင်း"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ခလုတ်ပါဝင်သော ကီးဘုတ်"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> အား ဝင်သုံးရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ခွင့်ပြုပါသလား။"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> အား <xliff:g id="USB_DEVICE">%2$s</xliff:g> ကို သုံးခွင့်ပြုမလား။\nဤအက်ပ်ကို အသံဖမ်းခွင့် ပေးမထားသော်လည်း ၎င်းသည် ဤ USB စက်ပစ္စည်းမှတစ်ဆင့် အသံများကို ဖမ်းယူနိုင်ပါသည်။"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> အား ဝင်သုံးရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ခွင့်ပြုပါသလား။"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ဆောင်ရွက်ရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ဖွင့်လိုပါသလား။"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ကို သုံးရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ဖွင့်မလား။\nဤအက်ပ်ကို အသံဖမ်းခွင့် ပေးမထားသော်လည်း ၎င်းသည် ဤ USB စက်ပစ္စည်းမှတစ်ဆင့် အသံများကို ဖမ်းယူနိုင်ပါသည်။"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ဆောင်ရွက်ရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ဖွင့်လိုပါသလား။"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ဒီUSBပစ္စည်းနှင့်ဘယ်အပ်ပလီကေးရှင်းမှ အလုပ်မလုပ်ပါ။ ပိုမိုသိရန် <xliff:g id="URL">%1$s</xliff:g>တွင် လေ့လာပါ"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USBတွဲဖက်ပစ္စည်းများ"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ချိတ်ဆက်သည့်အခါ <xliff:g id="APPLICATION">%1$s</xliff:g> ကို အမြဲဖွင့်ပါ"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ချိတ်ဆက်သည့်အခါ <xliff:g id="APPLICATION">%1$s</xliff:g> ကို အမြဲဖွင့်ပါ"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"USB အမှားရှာဖွေပြင်ဆင်ခြင်း ခွင့်ပြုပါမည်လား?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"ဒီကွန်ပျူတာရဲ့ RSA key fingerprint ကတော့:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g> ဖြစ်ပါသည်"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"ဤကွန်ပျူတာ၏ RSA သော့လက်ဗွေ-\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"ဒီကွန်ပျူတာမှ အမြဲခွင့်ပြုရန်"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"ခွင့်ပြုရန်"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB အမှားပြင်ဆင်ခြင်း ခွင့်မပြုပါ"</string>
@@ -110,8 +110,8 @@
     <string name="accessibility_phone_button" msgid="6738112589538563574">"ဖုန်း"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"အသံ အကူအညီ"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"သော့ဖွင့်ရန်"</string>
-    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"လက်ဗွေရာကို စောင့်နေပါသည်"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"လက်ဗွေရာ မသုံးဘဲ ဖွင့်ပါ"</string>
+    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"လက်ဗွေကို စောင့်နေသည်"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"လက်ဗွေ မသုံးဘဲ ဖွင့်ပါ"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"မျက်နှာ စကင်ဖတ်နေသည်"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"ပို့ရန်"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"အကြောင်းကြားချက်များကို စီမံရန်"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"အတည်ပြုပြီးပြီ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"အပြီးသတ်ရန်အတွက် \'အတည်ပြုရန်\' ကို တို့ပါ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"အထောက်အထားစိစစ်ပြီးပြီ"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ပင်နံပါတ်သုံးရန်"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ပုံစံကို သုံးရန်"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"စကားဝှက် သုံးရန်"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ပင်နံပါတ် မှားနေသည်"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ပုံစံ မှားနေသည်"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"စကားဝှက် မှားနေသည်"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"မှားသည့် အကြိမ် အရေအတွက် အလွန်များသည်။\n<xliff:g id="NUMBER">%d</xliff:g>စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"လက်ဗွေအာရုံခံကိရိယာကို တို့ပါ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"လက်ဗွေ သင်္ကေတ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"သင့်ကို ရှာဖွေနေသည်…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"အကြောင်းကြားချက်များ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ဖလက်ရှ်မီး"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ကင်မရာကို သုံးနေသည်"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"မိုဘိုင်းဒေတာ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ဒေတာ သုံးစွဲမှု"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ကျန်ရှိ ဒေတာ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 9e1c5db..c213b10 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfigurer inndatametoder"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fysisk tastatur"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Vil du gi <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vil du gi <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne appen har ikke fått tillatelse til å spille inn, men kan ta opp lyd med denne USB-enheten."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Vil du gi <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vil du åpne <xliff:g id="APPLICATION">%1$s</xliff:g> for å behandle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Vil du åpne <xliff:g id="APPLICATION">%1$s</xliff:g> for å håndtere <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne appen har ikke fått tillatelse til å spille inn, men kan ta opp lyd med denne USB-enheten."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vil du åpne <xliff:g id="APPLICATION">%1$s</xliff:g> for å behandle <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Ingen installerte apper støtter dette USB-tilbehøret. Les mer om tilbehøret på <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-enhet"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Bekreftet"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Trykk på Bekreft for å fullføre"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentisert"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Bruk PIN-kode"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Bruk mønster"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Bruk passord"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Feil PIN-kode"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Feil mønster"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Feil passord"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"For mange ugyldige forsøk.\nPrøv på nytt om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Trykk på fingeravtrykkssensoren"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon for fingeravtrykk"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Ser etter deg …"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Varsler"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lommelykt"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kameraet er i bruk"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobildata"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Databruk"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Gjenværende data"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 5a00002..8006279 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"इनपुट विधिहरू सेटअप गर्नुहोस्"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"वास्तविक किबोर्ड"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_DEVICE">%2$s</xliff:g> माथि पहुँच राख्ने अनुमति दिने हो?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_DEVICE">%2$s</xliff:g> माथि पहुँच राख्न अनुमति दिने हो?\nयो अनुप्रयोगलाई रेकर्ड गर्ने अनुमति प्रदान गरिएको छैन तर यसले USB यन्त्रमार्फत अडियो क्याप्चर गर्न सक्छ।"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> माथि पहुँच राख्ने अनुमति दिने हो?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> को व्यवस्थापन गर्न <xliff:g id="APPLICATION">%1$s</xliff:g> खोल्ने हो?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> को व्यवस्थापन गर्न <xliff:g id="APPLICATION">%1$s</xliff:g> खोल्ने हो?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"यस USB उपकरणसँग स्थापित अनुप्रयोग काम गर्दैन। यस उपकरणको बारेमा <xliff:g id="URL">%1$s</xliff:g> मा धेरै जान्नुहोस्"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB सहयोगी"</string>
@@ -58,7 +59,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> जडान भएको बेला सधैँ <xliff:g id="APPLICATION">%1$s</xliff:g> खोल्नुहोस्"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> जडान भएको बेला सधैँ <xliff:g id="APPLICATION">%1$s</xliff:g> खोल्नुहोस्"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"USB डिबग गर्नको लागि अनुमति दिने हो?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"कम्प्युटरको RSA कुञ्जी औंलाछाप:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"कम्प्युटरको RSA कुञ्जीको फिंगरप्रिन्ट:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"यो कम्प्युटरबाट सधैँ अनुमति दिनुहोस्"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"अनुमति दिनुहोस्"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB डिबग गर्न अनुमति छैन"</string>
@@ -111,7 +112,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"आवाज सहायता"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"खोल्नुहोस्"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"फिंगरप्रिन्ट कुर्दै"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"तपाईँको फिंगरप्रिन्ट बिना नै अनलक गर्नुहोस्"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"आफ्नो फिंगरप्रिन्ट बिना नै अनलक गर्नुहोस्"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"अनुहार स्क्यान गर्दै"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"पठाउनुहोस्"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"सूचनाहरू व्यवस्थित गर्नुहोस्"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"पुष्टि भयो"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"पूरा गर्नका लागि पुष्टि गर्नुहोस् नामक विकल्पमा ट्याप गर्नुहोस्"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"प्रमाणीकरण गरियो"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN प्रयोग गर्नुहोस्"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ढाँचा प्रयोग गर्नुहोस्"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"पासवर्ड प्रयोग गर्नुहोस्"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN मिलेन"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ढाँचा मिलेन"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"पासवर्ड मिलेन"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"अत्यन्तै धेरै पटक गलत प्रयास गरिए। \n <xliff:g id="NUMBER">%d</xliff:g>सेकेन्ड पछि पुनः प्रयास गर्नुहोस्।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"फिंगरप्रिन्ट सेन्सरमा छुनुहोस्‌"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"फिंगरप्रिन्ट जनाउने आइकन"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"तपाईंलाई खोज्दै…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"अधिसूचनाहरू"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"फ्ल्यासलाइट"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"क्यामेरा प्रयोगमा छ"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"मोबाइल डेटा"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"डेटाको प्रयोग"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"बाँकी डेटा"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index dacbd53..61e4c33 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Invoermethoden instellen"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fysiek toetsenbord"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDeze app heeft geen opnamerechten gekregen, maar zou audio kunnen vastleggen via dit USB-apparaat."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="APPLICATION">%1$s</xliff:g> openen om <xliff:g id="USB_DEVICE">%2$s</xliff:g> te verwerken?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> openen om <xliff:g id="USB_DEVICE">%2$s</xliff:g> te verwerken?\nDeze app heeft geen opnamerechten gekregen, maar zou audio kunnen vastleggen via dit USB-apparaat."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="APPLICATION">%1$s</xliff:g> openen om <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> te verwerken?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Er werken geen geïnstalleerde apps met dit USB-accessoire. Meer informatie op: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-accessoire"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Bevestigd"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tik op Bevestigen om te voltooien"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Geverifieerd"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Pincode gebruiken"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Patroon gebruiken"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Wachtwoord gebruiken"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Onjuiste pincode"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Onjuist patroon"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Onjuist wachtwoord"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Te veel onjuiste pogingen.\nProbeer het over <xliff:g id="NUMBER">%d</xliff:g> seconden opnieuw."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Raak de vingerafdruksensor aan"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Vingerafdrukpictogram"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Jouw gezicht zoeken…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Meldingen"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Zaklamp"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Camera in gebruik"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiele data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datagebruik"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Resterende gegevens"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 2720abf..527d69f 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ଇନପୁଟ୍‍ ପଦ୍ଧତି ସେଟ୍‍ କରନ୍ତୁ"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ଫିଜିକଲ୍ କୀ’ବୋର୍ଡ୍"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ଆକ୍ସେସ୍‍ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ଆକ୍ସେସ୍ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ କି?\nଏହି ଆପ୍‌କୁ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ କିନ୍ତୁ ଏହି USB ଡିଭାଇସ୍ ଜରିଆରେ ଅଡିଓ କ୍ୟାପ୍ଟର୍ କରିପାରିବ।"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ଆକ୍ସେସ୍‍ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ନିୟନ୍ତ୍ରଣ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g> ଖୋଲିବେ?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ନିୟନ୍ତ୍ରଣ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g> ଖୋଲିବେ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ଇନଷ୍ଟଲ୍‍ ହୋଇଥିବା କୌଣସି ଆପ୍‍ ଏହି USB ଆକ୍ସେସୋରୀରେ କାମ କରେନାହିଁ। ଏହି ଆକ୍ସେସୋରୀ ବିଷୟରେ <xliff:g id="URL">%1$s</xliff:g>ରେ ଅଧିକ ଜାଣନ୍ତୁ"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB ଆକ୍ସେସରୀ"</string>
@@ -58,7 +59,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> କନେକ୍ଟ ଥିବାବେଳେ <xliff:g id="APPLICATION">%1$s</xliff:g> ସର୍ବଦା ଖୋଲନ୍ତୁ"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> କନେକ୍ଟ ଥିବାବେଳେ <xliff:g id="APPLICATION">%1$s</xliff:g> ସର୍ବଦା ଖୋଲନ୍ତୁ"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"USB ଡିବଗିଙ୍ଗ କରିବେ?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"କମ୍ପ୍ୟୁଟର୍‌ର RSA କୀ\' ଆଙ୍ଗୁଠି ଚିହ୍ନ ହେଉଛି:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"କମ୍ପ୍ୟୁଟର୍‌ର RSA କୀ ଫିଙ୍ଗରପ୍ରିଣ୍ଟ୍ ହେଉଛି:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"ସବୁବେଳେ ଏହି କମ୍ପ୍ୟୁଟର୍‌ରୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USBରେ ଡିବଗ୍‍ କରାଯାଇପାରିବ ନାହିଁ"</string>
@@ -110,8 +111,8 @@
     <string name="accessibility_phone_button" msgid="6738112589538563574">"ଫୋନ୍‍"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"ଭଏସ୍‌ ସହାୟକ"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"ଅନଲକ୍‌ କରନ୍ତୁ"</string>
-    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ପାଇଁ ଅପେକ୍ଷା କରିଛି"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"ଆଙ୍ଗୁଠିଚିହ୍ନ ବ୍ୟବହାର ନକରି ଅନଲକ୍‍ କରନ୍ତୁ"</string>
+    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"ଟିପଚିହ୍ନ ପାଇଁ ଅପେକ୍ଷା କରୁଛି"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"ଆପଣଙ୍କ ଟିପଚିହ୍ନ ବ୍ୟବହାର ନକରି ଅନଲକ୍‍ କରନ୍ତୁ"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"ଫେସ୍ ସ୍କାନିଙ୍ଗ କରାଯାଉଛି"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"ପଠାନ୍ତୁ"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ପରିଚାଳନା କରନ୍ତୁ"</string>
@@ -128,22 +129,15 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"ସୁନିଶ୍ଚିତ କରାଯାଇଛି"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"ସମ୍ପୂର୍ଣ୍ଣ କରିବାକୁ ସୁନିଶ୍ଚିତ କରନ୍ତୁରେ ଟାପ୍ କରନ୍ତୁ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ପ୍ରାମାଣିକତା ହୋଇଛି"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ପାଟର୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"ପାସ୍‌ୱାର୍ଡ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ଭୁଲ PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ଭୁଲ ପାଟର୍ନ"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ଭୁଲ ପାସ୍‌ୱାର୍ଡ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ଅନେକ ଥର ଭୁଲ ଚେଷ୍ଟା। \n <xliff:g id="NUMBER">%d</xliff:g>ସେକେଣ୍ଡରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ଟିପଚିହ୍ନ ସେନସର୍‌କୁ ଛୁଅଁନ୍ତୁ"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଆଇକନ୍"</string>
+    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ଟିପଚିହ୍ନ ଆଇକନ୍"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ଆପଣଙ୍କୁ ଚିହ୍ନଟ କରୁଛି…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"ମୁହଁ ଆଇକନ୍"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"କମ୍ପାଟିବିଲିଟୀ ଜୁମ୍ ବଟନ୍।"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ବିଜ୍ଞପ୍ତି"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ଫ୍ଲାସ୍‍ଲାଇଟ୍"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"କ୍ୟାମେରା ବ୍ୟବହାରରେ ଅଛି"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ମୋବାଇଲ୍‌ ଡାଟା"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ଡାଟାର ବ୍ୟବହାର"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ଅବଶିଷ୍ଟ ଡାଟା"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 805a580..18ddddf 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ਇਨਪੁਟ ਵਿਧੀਆਂ ਸੈਟ ਅਪ ਕਰੋ"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ਫਿਜੀਕਲ ਕੀ-ਬੋਰਡ"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"ਕੀ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ਤੱਕ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨੂੰ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"ਕੀ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨੂੰ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?\nਇਸ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਪਰ ਇਹ USB ਡੀਵਾਈਸ ਰਾਹੀਂ ਆਡੀਓ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"ਕੀ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ਤੱਕ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨੂੰ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"ਕੀ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ਨੂੰ ਵਰਤਣ ਲਈ <xliff:g id="APPLICATION">%1$s</xliff:g> ਖੋਲ੍ਹਣੀ ਹੈ?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"ਕੀ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ਨੂੰ ਵਰਤਣ ਲਈ <xliff:g id="APPLICATION">%1$s</xliff:g> ਖੋਲ੍ਹਣੀ ਹੈ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ਕੋਈ ਇੰਸਟੌਲ ਕੀਤੇ ਐਪਸ ਇਸ USB ਐਕਸੈਸਰੀ ਨਾਲ ਕੰਮ ਨਹੀਂ ਕਰਦੇ। <xliff:g id="URL">%1$s</xliff:g> ਤੇ ਇਸ ਐਕਸੈਸਰੀ ਬਾਰੇ ਹੋਰ ਜਾਣੋ"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB ਐਕਸੈਸਰੀ"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"ਪੁਸ਼ਟੀ ਕੀਤੀ ਗਈ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"ਪੂਰਾ ਕਰਨ ਲਈ ਪੁਸ਼ਟੀ ਕਰੋ \'ਤੇ ਟੈਪ ਕਰੋ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ਪਿੰਨ ਵਰਤੋ"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ਪੈਟਰਨ ਵਰਤੋ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"ਪਾਸਵਰਡ ਵਰਤੋ"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ਗਲਤ ਪਿੰਨ"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ਗਲਤ ਪੈਟਰਨ"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ਗਲਤ ਪਾਸਵਰਡ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ਬਹੁਤ ਸਾਰੀਆਂ ਗ਼ਲਤ ਕੋਸ਼ਿਸ਼ਾਂ।\n<xliff:g id="NUMBER">%d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਪ੍ਰਤੀਕ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ਤੁਹਾਡੀ ਪਛਾਣ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ਸੂਚਨਾਵਾਂ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ਫਲੈਸ਼ਲਾਈਟ"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ਕੈਮਰਾ ਵਰਤੋਂ ਵਿੱਚ ਹੈ"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ਮੋਬਾਈਲ ਡਾਟਾ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ਡਾਟਾ ਵਰਤੋਂ"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ਬਾਕੀ  ਡਾਟਾ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 16dfff3..44b4112 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfiguruj metody wprowadzania"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Klawiatura fizyczna"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacja nie ma uprawnień do nagrywania, ale może rejestrować dźwięk za pomocą tego urządzenia USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do urządzenia <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Otworzyć aplikację <xliff:g id="APPLICATION">%1$s</xliff:g> do obsługi urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na obsługę urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacja nie ma uprawnień do nagrywania, ale może rejestrować dźwięk za pomocą tego urządzenia USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Otworzyć aplikację <xliff:g id="APPLICATION">%1$s</xliff:g> do obsługi urządzenia <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Zainstalowane aplikacje nie działają z tym akcesorium USB. Więcej informacji: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Akcesorium USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potwierdzono"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Aby zakończyć, kliknij Potwierdź"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Uwierzytelniono"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Użyj kodu PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Użyj wzoru"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Użyj hasła"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Nieprawidłowy kod PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Nieprawidłowy wzór"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Nieprawidłowe hasło"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Zbyt wiele nieudanych prób.\n Spróbuj ponownie za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dotknij czytnika linii papilarnych"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona odcisku palca"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Szukam Cię…"</string>
@@ -386,8 +379,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Powiadomienia"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Latarka"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Aparat w użyciu"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilna transmisja danych"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Użycie danych"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Pozostały limit"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 25ca226..57d64f5 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para lidar com o <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para usar o <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para lidar com o <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Nenhum apl. instalado funciona com o USB. Saiba mais sobre o acessório em <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Acessório USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Toque em \"Confirmar\" para concluir"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticado"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Usar PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Usar padrão"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Usar senha"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN incorreto"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Padrão incorreto"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Senha incorreta"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Excesso de tentativas incorretas.\nTente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toque no sensor de impressão digital"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ícone de impressão digital"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Procurando você…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Câmera em uso"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dados móveis"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Uso de dados"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dados restantes"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index fdb98fa..6c80211 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos introdução"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Pretende permitir que a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> aceda ao dispositivo <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Pretende permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> aceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsta aplicação não recebeu autorização de gravação, mas pode capturar áudio através deste dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Pretende permitir que a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> aceda ao acessório <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Pretende abrir a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> para controlar o acessório <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Pretende abrir a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> para controlar o acessório <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsta aplicação não recebeu autorização de gravação, mas pode capturar áudio através deste dispositivo USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Pretende abrir a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> para controlar o acessório <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Nenhuma das aplicações instaladas funciona com o acessório USB. Saiba mais acerca do acessório em <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Acessório USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmado"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Toque em Confirmar para concluir."</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticado"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Utilizar PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Utilizar padrão"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Utilizar palavra-passe"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN incorreto."</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Padrão incorreto."</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Palavra-passe incorreta."</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Demasiadas tentativas incorretas.\nTente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toque no sensor de impressões digitais."</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ícone de impressão digital"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"À sua procura…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Câmara em utilização"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dados móveis"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Utilização de dados"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dados restantes"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 25ca226..57d64f5 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para lidar com o <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para usar o <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para lidar com o <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Nenhum apl. instalado funciona com o USB. Saiba mais sobre o acessório em <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Acessório USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Toque em \"Confirmar\" para concluir"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticado"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Usar PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Usar padrão"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Usar senha"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN incorreto"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Padrão incorreto"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Senha incorreta"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Excesso de tentativas incorretas.\nTente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toque no sensor de impressão digital"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ícone de impressão digital"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Procurando você…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Câmera em uso"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dados móveis"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Uso de dados"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dados restantes"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 171ca9a..a6bd29b 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Setați metode introducere text"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Tastatură fizică"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Permiteți <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Permiteți accesul aplicației <xliff:g id="APPLICATION">%1$s</xliff:g> la <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nPermisiunea de înregistrare nu a fost acordată aplicației, dar aceasta poate să înregistreze conținut audio prin intermediul acestui dispozitiv USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Permiteți <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Deschideți <xliff:g id="APPLICATION">%1$s</xliff:g> ca să gestioneze <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Deschideți <xliff:g id="APPLICATION">%1$s</xliff:g> pentru a gestiona <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nPermisiunea de înregistrare nu a fost acordată aplicației, dar aceasta poate să înregistreze conținut audio prin intermediul acestui dispozitiv USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Deschideți <xliff:g id="APPLICATION">%1$s</xliff:g> ca să gestioneze <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Aplic. instal. nu funcț. cu acest acces. USB. Aflați despre acest accesoriu la <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accesoriu USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmat"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Atingeți Confirmați pentru a finaliza"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentificat"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Folosiți PIN-ul"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Folosiți modelul"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Folosiți parola"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN greșit"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Model greșit"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Parolă greșită"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Prea multe încercări incorecte.\nÎncercați din nou peste <xliff:g id="NUMBER">%d</xliff:g> secunde."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Atingeți senzorul de amprente"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Pictograma amprentă"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Vă căutăm…"</string>
@@ -382,8 +375,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificări"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanternă"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Se folosește camera foto"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Date mobile"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Utilizarea datelor"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Date rămase"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 1d7f6c8..3459440 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Настройка способов ввода"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Физическая клавиатура"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Предоставить приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к устройству \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Предоставить приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к устройству \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nПриложению не разрешено вести запись, однако с помощью этого USB-устройства оно может записывать звук."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Предоставить приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к устройству \"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>\"?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Открыть приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" для управления устройством \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Открыть приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" для использования устройства \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nПриложению не разрешено вести запись, однако с помощью этого USB-устройства оно может записывать звук."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Открыть приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" для управления устройством \"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>\"?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Приложения не поддерживают это USB-устройство. Подробнее о нем читайте здесь: <xliff:g id="URL">%1$s</xliff:g>."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-устройство"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Подтверждено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Нажмите \"Подтвердить\""</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Аутентификация выполнена"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Использовать PIN-код"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Использовать графический ключ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Использовать пароль"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Неверный PIN-код."</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Неверный графический ключ."</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Неверный пароль."</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Слишком много неудачных попыток.\nПовторите через <xliff:g id="NUMBER">%d</xliff:g> сек."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Прикоснитесь к сканеру отпечатков пальцев."</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Значок отпечатка пальца"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Поиск лица…"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Уведомления"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Фонарик"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Используется камера"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобильный Интернет"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Передача данных"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Остается данных"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index fa1c109..ab3dc222 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ආදාන ක්‍රම සකසන්න"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"භෞතික යතුරු පුවරුව"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> හට <xliff:g id="USB_DEVICE">%2$s</xliff:g> වෙත පිවිසීමට ඉඩ දෙන්නද?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> වෙත ප්‍රවේශ වීමට <xliff:g id="USB_DEVICE">%2$s</xliff:g> හට ඉඩ දෙන්නද?\n මෙම යෙදුමට පටිගත කිරීම් අවසරයක් ලබා දී නොමැති නමුත් මෙම USB උපාංගය හරහා ශ්‍රව්‍ය ග්‍රහණය කර ගත හැකිය."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> හට <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> වෙත පිවිසීමට ඉඩ දෙන්නද?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> හැසිරවීමට <xliff:g id="APPLICATION">%1$s</xliff:g> විවෘත කරන්නද?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_DEVICE">%2$s</xliff:g> හැසිරවීමට විවෘත කරන්නද?\n මෙම යෙදුමට පටිගත කිරීම් අවසරයක් ලබා දී නොමැති නමුත් මෙම USB උපාංගය හරහා ශ්‍රව්‍ය ග්‍රහණය කර ගත හැකිය."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> හැසිරවීමට <xliff:g id="APPLICATION">%1$s</xliff:g> විවෘත කරන්නද?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"මෙම USB මෙවලම සමග ක්‍රියා කරන ස්ථාපිත යෙදුම් නොමැත. <xliff:g id="URL">%1$s</xliff:g> වලින් මෙම මෙවලම ගැන තව දැනගන්න"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB මෙවලම"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> සම්බන්ධ විට <xliff:g id="APPLICATION">%1$s</xliff:g> සැම විටම විවෘත කරන්න"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> සම්බන්ධ විට <xliff:g id="APPLICATION">%1$s</xliff:g> සැම විටම විවෘත කරන්න"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"USB නිදොස්කරණයට අවසර දෙනවද?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"මෙම පරිගණකයේ RSA යතුරු ඇඟිලි සටහන වන්නේ:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"මෙම පරිගණකයේ RSA යතුරු ඇඟිලි සලකුණ සටහන වන්නේ:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"සැම විටම මෙම පරිගණකයෙන් ඉඩ ලබා දෙන්න"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"ඉඩ දෙන්න"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB නිදොස්කරණය වෙත අවසර නැහැ"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"තහවුරු කළා"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"සම්පූර්ණ කිරීමට තහවුරු කරන්න තට්ටු කර."</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"සත්‍යාපනය විය"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN භාවිත කරන්න"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"රටාව භාවිත කරන්න"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"මුරපදය භාවිත කරන්න"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN එක වැරදියි"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"වැරදි රටාවකි"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"වැරදි මුරපදයකි"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"වැරදි උත්සාහයන් ගණන වැඩියි. තත්පර \n තත්පර <xliff:g id="NUMBER">%d</xliff:g>කින් නැවත උත්සාහ කරන්න."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ඇඟිලි සලකුණු සංවේදකය ස්පර්ශ කරන්න"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ඇඟිලි සලකුණු නිරූපකය"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ඔබව සොයමින්…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"දැනුම්දීම්"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"සැණෙළි ආලෝකය"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"කැමරාව භාවිතයේ ඇත"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ජංගම දත්ත"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"දත්ත භාවිතය"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ඉතිරි ඇති දත්ත"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index ddb0ed4..aa004b4 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nastavenie metód vstupu"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fyzická klávesnica"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> prístup k zariadeniu <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> pristupovať k zariadeniu <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTejto aplikácii nebolo udelené povolenie na nahrávanie, môže však snímať zvuk cez toto zariadenie USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> prístup k zariadeniu <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Otvoriť aplikáciu <xliff:g id="APPLICATION">%1$s</xliff:g> na použitie zariadenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Chcete spracovávať zariadenie <xliff:g id="USB_DEVICE">%2$s</xliff:g> pomocou aplikácie <xliff:g id="APPLICATION">%1$s</xliff:g>?\nTejto aplikácii nebolo udelené povolenie na nahrávanie, ale môže nasnímať zvuk cez toto zariadenie USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Otvoriť aplikáciu <xliff:g id="APPLICATION">%1$s</xliff:g> na použitie zariadenia <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"S týmto zariad. USB nefunguje žiadna nainštal. aplikácia. Ďalšie informácie na <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Periférne zariadenie USB"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Hlasový asistent"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Odomknúť"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Čaká sa na odtlačok prsta"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Odomknúť bez použitia odtlačku"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Odomknúť bez použitia odtlačku prsta"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"Skenovanie tváre"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Odoslať"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Spravovať upozornenia"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potvrdené"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Overenie dokončíte klepnutím na Potvrdiť"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Overené"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Použiť PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Použiť vzor"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Použiť heslo"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Nesprávny PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Nesprávny vzor"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Nesprávne heslo"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Príliš veľa nesprávnych pokusov. \nSkúste to znova o <xliff:g id="NUMBER">%d</xliff:g> s."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dotknite sa senzora odtlačkov prstov"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona odtlačku prsta"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Hľadáme vás…"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Upozornenia"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Baterka"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Fotoaparát sa používa"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilné dáta"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Spotreba dát"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Zostávajúce údaje"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 1af84fe..03fa751 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nastavi načine vnosa"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizična tipkovnica"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Ali aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> dovolite dostop do dodatka USB <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Ali aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> dovolite dostop do naprave <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacija sicer nima dovoljenja za snemanje, vendar bi lahko zajemala zvok prek te naprave USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Ali aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> dovolite dostop do dodatka USB <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Želite odpreti aplikacijo <xliff:g id="APPLICATION">%1$s</xliff:g> za upravljanje dodatka USB <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Želite odpreti aplikacijo <xliff:g id="APPLICATION">%1$s</xliff:g> za upravljanje naprave <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacija sicer nima dovoljenja za snemanje, vendar bi lahko zajemala zvok prek te naprave USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Želite odpreti aplikacijo <xliff:g id="APPLICATION">%1$s</xliff:g> za upravljanje dodatka USB <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Namešč. prog. ne delujejo s tem dodatkom USB. Več o tem dodatku preberite na <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Dodatek USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potrjeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Za dokončanje se dotaknite »Potrdite«"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Preverjena pristnost"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Uporabi kodo PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Uporabi vzorec"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Uporabi geslo"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Napačna koda PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Napačen vzorec"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Napačno geslo"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Preveč napačnih poskusov.\nPoskusite znova čez <xliff:g id="NUMBER">%d</xliff:g> s."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dotaknite se tipala prstnih odtisov"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona prstnih odtisov"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Preverjanje vašega obraza …"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obvestila"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svetilka"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Fotoaparat je v uporabi"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Prenos podatkov v mobilnem omrežju"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Poraba podatkov"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Preostala količina podatkov"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 344aae3..21915c9 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfiguro metodat e hyrjes"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Tastierë fizike"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Të lejohet <xliff:g id="APPLICATION">%1$s</xliff:g> të ketë qasje te <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Dëshiron të lejosh që <xliff:g id="APPLICATION">%1$s</xliff:g> të ketë qasje te <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nKëtij aplikacioni nuk i është dhënë leje për regjistrim, por mund të regjistrojë audio përmes kësaj pajisjeje USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Të lejohet <xliff:g id="APPLICATION">%1$s</xliff:g> të ketë qasje te <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Të hapet <xliff:g id="APPLICATION">%1$s</xliff:g> për të përdorur <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Dëshiron të hapësh <xliff:g id="APPLICATION">%1$s</xliff:g> që të përpunojë <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nKëtij aplikacioni nuk i është dhënë leje për regjistrim, por mund të regjistrojë audio përmes kësaj pajisjeje USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Të hapet <xliff:g id="APPLICATION">%1$s</xliff:g> për të përdorur <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Asnjë aplikacion i instaluar nuk punon me këtë ndihmës USB-je. Mëso më shumë rreth këtij ndihmësi në <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Qasja në USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Konfirmuar"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Trokit \"Konfirmo\" për ta përfunduar"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"U vërtetua"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Përdor kodin PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Përdor motivin"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Përdor fjalëkalimin"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Kod PIN i gabuar"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Motiv i gabuar"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Fjalëkalim i gabuar"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Shumë tentativa të pasakta.\nProvo përsëri brenda <xliff:g id="NUMBER">%d</xliff:g> sekondash."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Prek sensorin e gjurmës së gishtit"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona e gjurmës së gishtit"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Po të kërkojmë…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Njoftimet"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Elektriku"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera në përdorim"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Të dhënat celulare"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Përdorimi i të dhënave"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Të dhënat e mbetura"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index b36b9dc..64ab59b 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Подеси методе уноса"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Физичка тастатура"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Желите ли да дозволите да <xliff:g id="APPLICATION">%1$s</xliff:g> приступа уређају <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Желите ли да дозволите да <xliff:g id="APPLICATION">%1$s</xliff:g> приступа уређају <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nОва апликација нема дозволу за снимање, али би могла да снима звук помоћу овог USB уређаја."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Желите ли да дозволите да <xliff:g id="APPLICATION">%1$s</xliff:g> приступа уређају <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Желите ли да отворите апликацију <xliff:g id="APPLICATION">%1$s</xliff:g> да бисте користили уређај <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Желите ли да отворите апликацију <xliff:g id="APPLICATION">%1$s</xliff:g> ради руковања уређајем <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nОва апликација нема дозволу за снимање, али би могла да снима звук помоћу овог USB уређаја."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Желите ли да отворите апликацију <xliff:g id="APPLICATION">%1$s</xliff:g> да бисте користили уређај <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Инсталиране апликације не функционишу са овим USB помоћним уређајем. Сазнајте више о њему на адреси <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB помоћни уређај"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Потврђено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Додирните Потврди да бисте завршили"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Идентитет је потврђен"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Користите PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Користите шаблон"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Користите лозинку"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Погрешан PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Погрешан шаблон"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Погрешна лозинка"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Превише нетачних покушаја.\n Пробајте поново за <xliff:g id="NUMBER">%d</xliff:g> сек."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Додирните сензор за отисак прста"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Икона отиска прста"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Тражимо вас…"</string>
@@ -382,8 +375,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Обавештења"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Лампа"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Користи се камера"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобилни подаци"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Потрошња података"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Преостала количина података"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 24e0b1e..0a65cc7 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfigurera inmatningsmetoder"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fysiskt tangentbord"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Vill du ge <xliff:g id="APPLICATION">%1$s</xliff:g> åtkomst till <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vill du ge <xliff:g id="APPLICATION">%1$s</xliff:g> åtkomst till <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAppen har inte fått inspelningsbehörighet men kan spela in ljud via denna USB-enhet."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Vill du ge <xliff:g id="APPLICATION">%1$s</xliff:g> åtkomst till <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vill du öppna <xliff:g id="APPLICATION">%1$s</xliff:g> och hantera <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Vill du öppna <xliff:g id="APPLICATION">%1$s</xliff:g> för att hantera <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAppen har inte fått inspelningsbehörighet men kan spela in ljud via denna USB-enhet."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vill du öppna <xliff:g id="APPLICATION">%1$s</xliff:g> och hantera <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Inga appar fungerar med det här USB-tillbehöret. Läs mer om det på <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-tillbehör"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Bekräftat"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Slutför genom att trycka på Bekräfta"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentiserad"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Använd pinkod"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Använd grafiskt lösenord"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Använd lösenord"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Fel pinkod"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Fel grafiskt lösenord"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Fel lösenord"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"För många felaktiga försök.\nFörsök igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Tryck på fingeravtryckssensorn"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon för fingeravtryck"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Håller utkik efter dig …"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Aviseringar"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Ficklampa"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kameran används"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobildata"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Dataanvändning"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Återstående data"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 93f5b7d..48c1fab 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Weka mbinu za ingizo"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Kibodi halisi"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Ungependa kuruhusu <xliff:g id="APPLICATION">%1$s</xliff:g> ifikie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Ungependa kuruhusu <xliff:g id="APPLICATION">%1$s</xliff:g> ifikie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nProgramu hii haijapewa ruhusa ya kurekodi lakini inaweza kurekodi sauti kupitia kifaa hiki cha USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Ungependa kuruhusu <xliff:g id="APPLICATION">%1$s</xliff:g> ifikie <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Ungependa kufungua <xliff:g id="APPLICATION">%1$s</xliff:g> ili itumie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Ungependa kufungua <xliff:g id="APPLICATION">%1$s</xliff:g> ishughulikie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nProgramu hii haijapewa ruhusa ya kurekodi lakini inaweza kurekodi sauti kupitia kifaa hiki cha USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Ungependa kufungua <xliff:g id="APPLICATION">%1$s</xliff:g> ili itumie <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Hakuna programu zilizosakinishwa zinazofanya kazi na kifaa hiki cha USB. Pata maelezo zaidi kuhusu kifaa hiki kwenye <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Kifaa cha Usb"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"Fungua <xliff:g id="APPLICATION">%1$s</xliff:g> kila wakati <xliff:g id="USB_DEVICE">%2$s</xliff:g> inaunganishwa"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Fungua <xliff:g id="APPLICATION">%1$s</xliff:g> kila wakati <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> inaunganishwa"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"Ruhusu utatuaji wa USB?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"Alama ya kidole ya kitufe cha RSA ya kompyuta ni:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Kitambulisho dijitali cha kifunguo cha RSA cha kompyuta ni:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Ruhusu kutoka kwenye kompyuta hii kila wakati"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"Ruhusu"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Utatuzi wa USB hauruhusiwi"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Mapendekezo ya Sauti"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Fungua"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Inasubiri alama ya kidole"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Fungua bila kutumia kitambulisho chako"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Fungua bila kutumia alama ya kidole chako"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"Inachanganua uso"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Tuma"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Dhibiti arifa"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Imethibitishwa"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Gusa Thibitisha ili ukamilishe"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Umethibitishwa"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Tumia PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Tumia mchoro"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Tumia nenosiri"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Nambari ya PIN si sahihi"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Mchoro si sahihi"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Nenosiri si sahihi"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Majaribio mengi mno yasiyo sahihi.\nJaribu tena baada ya sekunde <xliff:g id="NUMBER">%d</xliff:g>."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Gusa kitambua alama ya kidole"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Aikoni ya alama ya kidole"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Inakutafuta…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Arifa"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Tochi"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera inatumika"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Data ya simu"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Matumizi ya data"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Data iliyosalia"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index a5aa91d..7263bf6 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"உள்ளீட்டு முறைகளை அமை"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"கைமுறை விசைப்பலகை"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐ அணுக, <xliff:g id="APPLICATION">%1$s</xliff:g> ஆப்ஸை அனுமதிக்கவா?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐப் பயன்படுத்த <xliff:g id="APPLICATION">%1$s</xliff:g>ஐ அனுமதிக்கவா?\nஇந்த ஆப்ஸிற்கு ரெக்கார்டு செய்வதற்கான அனுமதி வழங்கப்படவில்லை, எனினும் இந்த USB சாதனம் மூலம் ஆடியோவைப் பதிவுசெய்யும்."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ஐ அணுக, <xliff:g id="APPLICATION">%1$s</xliff:g> ஆப்ஸை அனுமதிக்கவா?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐக் கையாள, <xliff:g id="APPLICATION">%1$s</xliff:g> பயன்பாட்டைத் திறக்கவா?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐக் கையாள <xliff:g id="APPLICATION">%1$s</xliff:g>ஐத் திறக்கவா?\nஇந்த ஆப்ஸிற்கு ரெக்கார்டு செய்வதற்கான அனுமதி வழங்கப்படவில்லை, எனினும் இந்த USB சாதனம் மூலம் ஆடியோவைப் பதிவுசெய்ய முடியும்."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ஐக் கையாள, <xliff:g id="APPLICATION">%1$s</xliff:g> பயன்பாட்டைத் திறக்கவா?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"நிறுவிய ஆப்ஸ் எதுவும், USB துணைக்கருவியுடன் இயங்காது. <xliff:g id="URL">%1$s</xliff:g> இல் துணைக்கருவி குறித்து மேலும் அறிக"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB துணைக்கருவி"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> இணைக்கப்பட்டிருக்கையில், <xliff:g id="APPLICATION">%1$s</xliff:g>ஐ எப்போதும் திற"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> இணைக்கப்பட்டிருக்கையில், <xliff:g id="APPLICATION">%1$s</xliff:g>ஐ எப்போதும் திற"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"USB பிழைதிருத்தத்தை அனுமதிக்கவா?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"பின்வருவது கணினியின் RSA விசை கைரேகையாகும்:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"கணினியின் RSA விசை ஃபிங்கர்பிரிண்ட்:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"இந்தக் கணினியிலிருந்து எப்போதும் அனுமதி"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"அனுமதி"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB பிழைதிருத்தம் அனுமதிக்கப்படவில்லை"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"உறுதிப்படுத்தப்பட்டது"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"முடிக்க \'உறுதிப்படுத்து\' என்பதை தட்டவும்"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"அங்கீகரிக்கப்பட்டது"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"பின்னைப் பயன்படுத்து"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"பேட்டர்னைப் பயன்படுத்து"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"கடவுச்சொல்லைப் பயன்படுத்து"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"தவறான பின்"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"தவறான பேட்டர்ன்"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"தவறான கடவுச்சொல்"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"பல தவறான முயற்சிகள்.\n<xliff:g id="NUMBER">%d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"கைரேகை சென்சாரைத் தொடவும்"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"கைரேகை ஐகான்"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"உங்கள் முகத்தைத் தேடுகிறது…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"அறிவிப்புகள்"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"டார்ச் லைட்"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"கேமரா உபயோகத்திலுள்ளது"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"மொபைல் டேட்டா"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"டேட்டா உபயோகம்"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"மீதமுள்ள தரவு"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index c6b2bb7..af330f18f 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ఇన్‌పుట్ పద్ధతులను సెటప్ చేయండి"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"భౌతిక కీబోర్డ్"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ని యాక్సెస్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ని అనుమతించాలా?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>యాక్సెస్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ను అనుమతించాలా?\nఈ యాప్‌నకు రికార్డ్ చేసే అనుమతి మంజూరు చేయబడలేదు, కానీ ఈ USB పరికరం ద్వారా ఆడియోను క్యాప్చర్ చేయగలదు."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ని యాక్సెస్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ని అనుమతించాలా?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ని నిర్వహించడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ని తెరవాలా?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ని నిర్వహించడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ని తెరవాలా?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ఈ USB ఉపకరణంతో ఇన్‌స్టాల్ చేయబడిన అనువర్తనాలు ఏవీ పని చేయవు. ఈ ఉపకరణం గురించి <xliff:g id="URL">%1$s</xliff:g>లో మరింత తెలుసుకోండి"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB ఉపకరణం"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"నిర్ధారించబడింది"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"పూర్తి చేయడానికి \"నిర్ధారించు\" నొక్కండి"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ప్రామాణీకరించబడింది"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"పిన్‌ను ఉపయోగించు"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ఆకృతిని ఉపయోగించు"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"పాస్‌వర్డ్‌ను ఉపయోగించు"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"పిన్ తప్పు"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ఆకృతి తప్పు"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"పాస్‌వర్డ్ తప్పు"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"చాలా ఎక్కువ తప్పు ప్రయత్నాలు చేశారు.\n<xliff:g id="NUMBER">%d</xliff:g> సెకన్ల తర్వాత మళ్లీ ప్రయత్నించండి."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"వేలిముద్ర సెన్సార్‌ను తాకండి"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"వేలిముద్ర చిహ్నం"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"మీ కోసం చూస్తోంది…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"నోటిఫికేషన్‌లు"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ఫ్లాష్‌లైట్"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"కెమెరా ఉపయోగంలో ఉంది"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"మొబైల్ డేటా"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"డేటా వినియోగం"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"మిగిలిన డేటా"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 2907524..fc062b4 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ตั้งค่าวิธีการป้อนข้อมูล"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"แป้นพิมพ์บนเครื่อง"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"อนุญาตให้ <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึง <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"อนุญาตให้ <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึง <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม\nแอปนี้ไม่ได้รับอนุญาตให้อัดเสียงแต่จะอัดเสียงผ่านอุปกรณ์ USB นี้ได้"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"อนุญาตให้ <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึง <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ไหม"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"เปิด <xliff:g id="APPLICATION">%1$s</xliff:g> เพื่อจัดการ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"เปิด <xliff:g id="APPLICATION">%1$s</xliff:g> เพื่อจัดการ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ใช่ไหม\nแอปนี้ไม่ได้รับอนุญาตให้อัดเสียงแต่จะอัดเสียงผ่านอุปกรณ์ USB นี้ได้"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"เปิด <xliff:g id="APPLICATION">%1$s</xliff:g> เพื่อจัดการ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ไหม"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"แอปพลิเคชันที่ติดตั้งใช้กับอุปกรณ์ USB นี้ไม่ได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับอุปกรณ์เสริมนี้ที่ <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"อุปกรณ์เสริม USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"ยืนยันแล้ว"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"แตะยืนยันเพื่อดำเนินการให้เสร็จสมบูรณ์"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ตรวจสอบสิทธิ์แล้ว"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ใช้ PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ใช้รูปแบบ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"ใช้รหัสผ่าน"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN ไม่ถูกต้อง"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"รูปแบบไม่ถูกต้อง"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"รหัสผ่านไม่ถูกต้อง"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ดำเนินการไม่ถูกต้องหลายครั้งเกินไป\nลองอีกครั้งใน <xliff:g id="NUMBER">%d</xliff:g> วินาที"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"แตะเซ็นเซอร์ลายนิ้วมือ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ไอคอนลายนิ้วมือ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"กำลังหาใบหน้าคุณ…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"การแจ้งเตือน"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ไฟฉาย"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ใช้กล้องอยู่"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"เน็ตมือถือ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"การใช้อินเทอร์เน็ต"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ข้อมูลที่เหลืออยู่"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index ce8c88b..37dd49f 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"I-set up paraan ng pag-input"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Aktwal na keyboard"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Payagan ang <xliff:g id="APPLICATION">%1$s</xliff:g> na ma-access ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Payagan ang <xliff:g id="APPLICATION">%1$s</xliff:g> na i-access ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nHindi nabigyan ng pahintulot ang app na ito para mag-record pero nakakapag-capture ito ng audio sa pamamagitan ng USB device na ito."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Payagan ang <xliff:g id="APPLICATION">%1$s</xliff:g> na ma-access ang <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Buksan ang <xliff:g id="APPLICATION">%1$s</xliff:g> upang pamahalaan ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Buksan ang <xliff:g id="APPLICATION">%1$s</xliff:g> para pangasiwaan ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nHindi nabigyan ng pahintulot ang app na ito para mag-record pero nakakapag-capture ito ng audio sa pamamagitan ng USB device na ito."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Buksan ang <xliff:g id="APPLICATION">%1$s</xliff:g> upang pamahalaan ang <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Wala sa mga na-install na app ang gumagana sa USB accessory na ito. Matuto pa tungkol sa accessory na ito sa <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB accessory"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Nakumpirma"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"I-tap ang Kumpirmahin para kumpletuhin"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Na-authenticate"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Gumamit ng PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Gumamit ng pattern"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Gumamit ng password"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Maling PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Maling pattern"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Maling password"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Masyadong maraming maling pagsubok.\nSubukan ulit sa loob ng <xliff:g id="NUMBER">%d</xliff:g> (na) segundo."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Pindutin ang fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icon ng fingerprint"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Hinahanap ka…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Mga Notification"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flashlight"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Ginagamit na camera"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Paggamit ng data"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Natitirang data"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 7976014..c052f4a 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Giriş yöntemlerini ayarla"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fiziksel klavye"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına erişmesine izin verilsin mi?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına erişmesine izin verilsin mi?\nBu uygulamaya kayıt izni verilmemiş ancak bu USB cihazı aracılığıyla sesleri yakalayabilir."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> aksesuarına erişmesine izin verilsin mi?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazını işlemek için <xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması açılsın mı?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> için <xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması açılsın mı?\n Bu uygulamaya kayıt izni verilmemiş, ancak bu USB cihazı aracılığıyla sesleri yakalabilir."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> aksesuarını işlemek için <xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması açılsın mı?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Bu USB aksesuarıyla çalışan yüklü uygulama yok. Bu aksesuar hakkında bilgi için: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB aksesuarı"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Onaylandı"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tamamlamak için Onayla\'ya dokunun"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Kimliği Doğrulandı"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN kullan"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Deseni kullan"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Şifre kullan"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Yanlış PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Yanlış desen"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Yanlış şifre"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Çok fazla yanlış giriş yapıldı.\n<xliff:g id="NUMBER">%d</xliff:g> saniye içinde tekrar deneyin."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Parmak izi sensörüne dokunun"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Parmak izi simgesi"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Yüzünüz tanınmaya çalışılıyor…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Bildirimler"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Fener"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera kullanımda"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobil veri"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Veri kullanımı"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Kalan veri"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index ea2f376..de6b6f2 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Налаштувати методи введення"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Фізична клавіатура"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Надати додатку <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до такого аксесуара: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Надати додатку <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nЦей додаток не має дозволу на записування звуку, але може фіксувати його через цей USB-пристрій."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Надати додатку <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до такого аксесуара: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Відкрити додаток <xliff:g id="APPLICATION">%1$s</xliff:g>, щоб використовувати такий аксесуар: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Працювати з пристроєм \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\" у додатку <xliff:g id="APPLICATION">%1$s</xliff:g>?\nУ цього додатка немає дозволів на запис, але він може передавати звук у USB-пристрій."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Відкрити додаток <xliff:g id="APPLICATION">%1$s</xliff:g>, щоб використовувати такий аксесуар: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Установлені прогр. не працюють із цим аксесуаром USB. Більше про цей аксесуар: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Пристрій USB"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Голосові підказки"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Розблокувати"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Очікується відбиток пальця"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Розблокувати без цифрового відбитка"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Розблокувати без відбитка пальця"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"Сканування обличчя"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Надіслати"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Керувати сповіщеннями"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Підтверджено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Щоб завершити, натисніть \"Підтвердити\""</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Автентифіковано"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Ввести PIN-код"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Намалювати ключ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Ввести пароль"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Неправильний PIN-код"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Неправильний ключ"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Неправильний пароль"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Забагато невдалих спроб.\nПовторіть за <xliff:g id="NUMBER">%d</xliff:g> с."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Торкніться сканера відбитків пальців"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Значок відбитка пальця"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Пошук обличчя…"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Сповіщення"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Ліхтарик"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Використовується камера"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобільне передавання даних"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Використання даних"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Залишилося даних"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 1c28431..b361a4a 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ان پٹ کے طریقوں کو ترتیب دیں"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"طبعی کی بورڈ"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> کو <xliff:g id="USB_DEVICE">%2$s</xliff:g> تک رسائی حاصل کرنے کی اجازت دیں؟"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"‏<xliff:g id="APPLICATION">%1$s</xliff:g> کو <xliff:g id="USB_DEVICE">%2$s</xliff:g> تک رسائی دیں؟\nاس ایپ کو ریکارڈ کی اجازت عطا نہیں کی گئی ہے مگر اس USB آلہ سے کیپچر کر سکتے ہیں۔"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> کو <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> تک رسائی حاصل کرنے کی اجازت دیں؟"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ہینڈل کرنے کیلئے <xliff:g id="APPLICATION">%1$s</xliff:g> کھولیں؟"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ہینڈل کرنے کیلئے <xliff:g id="APPLICATION">%1$s</xliff:g> کھولیں؟"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"‏اس USB لوازم کے ساتھ کوئی انسٹال کردہ ایپس کام نہیں کرتی ہیں۔ <xliff:g id="URL">%1$s</xliff:g> پر مزید جانیں"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"‏USB لوازم"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"تصدیق شدہ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"مکمل کرنے کیلئے \'تصدیق کریں\' تھپتھپائیں"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"تصدیق کردہ"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"‏PIN استعمال کریں"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"پیٹرن کا استعمال کریں"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"پاس ورڈ استعمال کریں"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"‏غلط PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"غلط پیٹرن"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"غلط پاس ورڈ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"کافی زیادہ غلط کوششیں کی گئیں۔\n <xliff:g id="NUMBER">%d</xliff:g> سیکنڈ بعد دوبارہ کوشش کریں۔"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"فنگر پرنٹ سینسر پر ٹچ کریں"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"فنگر پرنٹ آئیکن"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"آپ کے لیے تلاش کیا جا رہا ہے…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"اطلاعات"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"فلیش لائٹ"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"کیمرا زیر استعمال ہے"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"موبائل ڈیٹا"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ڈیٹا کا استعمال"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"باقی ڈیٹا"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index c3e39e5..5c077d8 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Kiritish usullarini moslash"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Tashqi tugmatag"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_DEVICE">%2$s</xliff:g> qurilmasidan foydalanishga ruxsat berilsinmi?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_DEVICE">%2$s</xliff:g> qurilmasidan foydalanish uchun ruxsat berilsinmi?\nBu ilovaga yozib olish ruxsati berilmagan, lekin shu USB orqali ovozlarni yozib olishi mumkin."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> qurilmasidan foydalanishga ruxsat berilsinmi?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> bilan ishlash uchun <xliff:g id="APPLICATION">%1$s</xliff:g> ochilsinmi?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_DEVICE">%2$s</xliff:g> qurilmasidan foydalanish uchun ruxsat berilsinmi?\nBu ilovaga yozib olish ruxsati berilmagan, lekin shu USB orqali ovozlarni yozib olishi mumkin."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> bilan ishlash uchun <xliff:g id="APPLICATION">%1$s</xliff:g> ochilsinmi?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Bu USB jihoz bilan ishlash uchun dastur o‘rnatilmagan.Ushbu jihoz haqida: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB jihoz"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Tasdiqlangan"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tasdiqlash uchun tegining"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Tasdiqlandi"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN kod kiritish"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Grafik kalitdan foydalanish"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Paroldan foydalanish"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN kod xato"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Grafik kalit xato"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Parol xato"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Xato urinishlar soni oshib ketdi! \n <xliff:g id="NUMBER">%d</xliff:g> soniyadan keyin qayta urining."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Barmoq izi skaneriga tegining"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Barmoq izi belgisi"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Yuzingiz tekshirilmoqda…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Bildirishnomalar"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Fonar"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera ishlatilmoqda"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobil internet"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Trafik sarfi"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Qolgan trafik"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d2da39b..88849c8 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Thiết lập phương thức nhập"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Bàn phím vật lý"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Cho phép <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Cho phép <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập vào <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nỨng dụng này chưa được cấp quyền ghi âm nhưng vẫn có thể ghi âm thông qua thiết bị USB này."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Cho phép <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Mở <xliff:g id="APPLICATION">%1$s</xliff:g> để điều khiển <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Mở <xliff:g id="APPLICATION">%1$s</xliff:g> để điều khiển <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDù chưa được cấp quyền ghi âm, nhưng ứng dụng có thể ghi âm thông qua thiết bị USB này."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Mở <xliff:g id="APPLICATION">%1$s</xliff:g> để điều khiển <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Không có ứng dụng được cài đặt nào hoạt động với phụ kiện USB này. Tìm hiểu thêm về phụ kiện này tại <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Phụ kiện USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Ðã xác nhận"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Nhấn vào Xác nhận để hoàn tất"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Đã xác thực"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Dùng mã PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Dùng hình mở khóa"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Dùng mật khẩu"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Mã PIN sai"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Hình mở khóa sai"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Mật khẩu sai"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Bạn đã nhập sai quá nhiều lần.\nHãy thử lại sau <xliff:g id="NUMBER">%d</xliff:g> giây."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Chạm vào cảm biến vân tay"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Biểu tượng vân tay"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Đang tìm kiếm bạn…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Thông báo"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Đèn pin"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Máy ảnh đang được sử dụng"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dữ liệu di động"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Sử dụng dữ liệu"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dữ liệu còn lại"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 551e54e..cdc2070 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"设置输入法"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"物理键盘"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"要允许<xliff:g id="APPLICATION">%1$s</xliff:g>访问<xliff:g id="USB_DEVICE">%2$s</xliff:g>吗?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"是否允许<xliff:g id="APPLICATION">%1$s</xliff:g>访问<xliff:g id="USB_DEVICE">%2$s</xliff:g>?\n此应用未获得录音权限,但能通过此 USB 设备录制音频。"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"要允许<xliff:g id="APPLICATION">%1$s</xliff:g>访问<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>吗?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"要打开<xliff:g id="APPLICATION">%1$s</xliff:g>来处理<xliff:g id="USB_DEVICE">%2$s</xliff:g>吗?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"要打开<xliff:g id="APPLICATION">%1$s</xliff:g>来使用<xliff:g id="USB_DEVICE">%2$s</xliff:g>吗?\n此应用未获得录音权限,但能通过此 USB 设备录制音频。"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"要打开<xliff:g id="APPLICATION">%1$s</xliff:g>来处理<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>吗?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"未安装此USB配件适用的应用。要了解此配件的详情,请访问:<xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB配件"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"已确认"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"点按“确认”即可完成"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"已经过身份验证"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"使用 PIN 码"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"使用图案"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"使用密码"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN 码错误"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"图案错误"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"密码错误"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"输错次数过多。\n请在 <xliff:g id="NUMBER">%d</xliff:g> 秒后重试。"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"请触摸指纹传感器"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"指纹图标"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"正在查找您的面孔…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"手电筒"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"相机正在使用中"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"移动数据"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"流量使用情况"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"剩余流量"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 206fcfc..a69bb7b 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"設定輸入法"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"實體鍵盤"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n此應用程式尚未獲授予錄音權限,但可透過此 USB 裝置記錄音訊。"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>」嗎?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」處理「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」應用程式來控制「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n此應用程式尚未獲授予錄音權限,但可透過此 USB 裝置記錄音訊。"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」處理「<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>」嗎?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"已安裝的應用程式均無法存取這個 USB 配件,如要進一步瞭解這個配件,請瀏覽 <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB 配件"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"已確認"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"輕按 [確定] 以完成"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"驗證咗"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"使用 PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"使用圖案"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"使用密碼"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN 錯誤"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"圖案錯誤"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"密碼錯誤"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"輸入錯誤的次數太多,\n請於 <xliff:g id="NUMBER">%d</xliff:g> 秒後再試。"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"請輕觸指紋感應器"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"指紋圖示"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"正在搜尋您的臉孔…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"電筒"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"相機使用中"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"流動數據"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"數據用量"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"剩餘資料"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index c1f299d..dedaebf 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"設定輸入法"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"實體鍵盤"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n這個應用程式未取得錄製權限,但可以透過這部 USB 裝置錄製音訊。"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>」嗎?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」處理「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」來使用「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n這個應用程式未取得錄製內容的權限,但可以透過這部 USB 裝置錄製音訊。"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」處理「<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>」嗎?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"已安裝的應用程式均無法存取這個 USB 配件,如要進一步瞭解這個配件,請造訪 <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB 配件"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"確認完畢"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"輕觸 [確認] 完成驗證設定"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"已通過驗證"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"使用 PIN 碼"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"使用解鎖圖案"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"使用密碼"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN 碼錯誤"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"圖案錯誤"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"密碼錯誤"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"錯誤次數過多,\n請於 <xliff:g id="NUMBER">%d</xliff:g> 秒後再試。"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"請輕觸指紋感應器"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"指紋圖示"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"正在尋找你的臉孔…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"手電筒"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"正在使用相機"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"行動數據"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"數據用量"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"剩餘資料"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 37eca51..192bfb4 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Izilungiselelo zezindlela zokufakwayo"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Ukwakheka kwekhibhodi"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Vumela i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukufinyelela i-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vumela i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuthi ifinyelele ku-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLolu hlelo lokusebenza alunikeziwe imvume yokurekhoda kodwa lingathatha umsindo ngale divayisi ye-USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Vumela i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukufinyelela i-<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vula i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuze uphath i-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Vula i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuze uphathe i-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLolu hlelo lokusebenza alinikeziwe imvume yokurekhoda kodwa lingathatha umsindo ngale divayisi ye-USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vula i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuze uphath i-<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Azikho izinhlelo zokusebenza ezisebenze ngezinto ze-USB. Funda okwengeziwe ngale into kwi <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"ama-accessory e-USB"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Isisekeli sezwi"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Vula"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Ilindele izigxivizo zeminwe"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Vula ngaphandle kokusebenzisa izigxivizo zakho zeminwe"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Vula ngaphandle kokusebenzisa izigxivizo zeminwe zakho"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"Ukuskena ubuso"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Thumela"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Phatha izaziso"</string>
@@ -128,21 +128,14 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Kuqinisekisiwe"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Thepha okuthi Qinisekisa ukuze uqedele"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Kugunyaziwe"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
-    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Thinta inzwa yesigxivizo somunwe"</string>
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Sebenzisa iphinikhodi"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Sebenzisa iphethini"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Sebenzisa iphasiwedi"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Iphinikhodi engalungile"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Iphethini engalungile"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Iphasiwedi engalungile"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Imizamo eminingi kakhulu engalungile.\nZama futhi kumasekhondi angu-<xliff:g id="NUMBER">%d</xliff:g>."</string>
+    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Thinta inzwa yesigxivizo zeminwe"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Isithonjana sezigxivizo zeminwe"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Kufunwa wena…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Isithonjana sobuso"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Izaziso"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"I-Flashlight"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Ikhamera esetshenziswayo"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Idatha yeselula"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Ukusetshenziswa kwedatha"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Idatha esele"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 105b27e..efcc2c4 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -117,7 +117,7 @@
 
     <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
     <string name="quick_settings_tiles_stock" translatable="false">
-        wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night
+        wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,controls
     </string>
 
     <!-- The tiles to display in QuickSettings -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8335c11..3cc683a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -129,6 +129,9 @@
     <!-- Prompt for the USB device confirm dialog [CHAR LIMIT=80] -->
     <string name="usb_device_confirm_prompt">Open <xliff:g id="application">%1$s</xliff:g> to handle <xliff:g id="usb_device">%2$s</xliff:g>?</string>
 
+    <!-- Prompt for the USB device confirm dialog with warning text for USB device dialogs.  [CHAR LIMIT=200] -->
+    <string name="usb_device_confirm_prompt_warn">Open <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> to handle <xliff:g id="usb_device" example="USB Headphones">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device.</string>
+
     <!-- Prompt for the USB accessory confirm dialog [CHAR LIMIT=80] -->
     <string name="usb_accessory_confirm_prompt">Open <xliff:g id="application">%1$s</xliff:g> to handle <xliff:g id="usb_accessory">%2$s</xliff:g>?</string>
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 2ef0422..748f356 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -115,4 +115,15 @@
             Log.e(TAG, "Failed to clean up screenshot of recents animation", e);
         }
     }
+
+    /**
+     * @see {{@link IRecentsAnimationController#setWillFinishToHome(boolean)}}.
+     */
+    public void setWillFinishToHome(boolean willFinishToHome) {
+        try {
+            mAnimationController.setWillFinishToHome(willFinishToHome);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to set overview reached state", e);
+        }
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index d45603f..ebac3d9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -33,10 +33,9 @@
 import com.android.internal.util.LatencyTracker;
 import com.android.internal.widget.LockPatternChecker;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockscreenCredential;
 import com.android.systemui.R;
 
-import java.util.Arrays;
-
 /**
  * Base class for PIN and password unlock screens.
  */
@@ -132,19 +131,20 @@
     protected void verifyPasswordAndUnlock() {
         if (mDismissing) return; // already verified but haven't been dismissed; don't do it again.
 
-        final byte[] entry = getPasswordText();
+        final LockscreenCredential password =
+                LockscreenCredential.createPassword(getPasswordText());
         setPasswordEntryInputEnabled(false);
         if (mPendingLockCheck != null) {
             mPendingLockCheck.cancel(false);
         }
 
         final int userId = KeyguardUpdateMonitor.getCurrentUser();
-        if (entry.length <= MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT) {
+        if (password.size() <= MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT) {
             // to avoid accidental lockout, only count attempts that are long enough to be a
             // real password. This may require some tweaking.
             setPasswordEntryInputEnabled(true);
             onPasswordChecked(userId, false /* matched */, 0, false /* not valid - too short */);
-            Arrays.fill(entry, (byte) 0);
+            password.zeroize();
             return;
         }
 
@@ -152,9 +152,9 @@
             LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL);
             LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL_UNLOCKED);
         }
-        mPendingLockCheck = LockPatternChecker.checkPassword(
+        mPendingLockCheck = LockPatternChecker.checkCredential(
                 mLockPatternUtils,
-                entry,
+                password,
                 userId,
                 new LockPatternChecker.OnCheckCallback() {
 
@@ -166,7 +166,7 @@
                         }
                         onPasswordChecked(userId, true /* matched */, 0 /* timeoutMs */,
                                 true /* isValidPassword */);
-                        Arrays.fill(entry, (byte) 0);
+                        password.zeroize();
                     }
 
                     @Override
@@ -181,7 +181,7 @@
                             onPasswordChecked(userId, false /* matched */, timeoutMs,
                                     true /* isValidPassword */);
                         }
-                        Arrays.fill(entry, (byte) 0);
+                        password.zeroize();
                     }
 
                     @Override
@@ -192,7 +192,7 @@
                             LatencyTracker.getInstance(mContext).onActionEnd(
                                     ACTION_CHECK_CREDENTIAL_UNLOCKED);
                         }
-                        Arrays.fill(entry, (byte) 0);
+                        password.zeroize();
                     }
                 });
     }
@@ -223,7 +223,7 @@
     }
 
     protected abstract void resetPasswordText(boolean animate, boolean announce);
-    protected abstract byte[] getPasswordText();
+    protected abstract CharSequence getPasswordText();
     protected abstract void setPasswordEntryEnabled(boolean enabled);
     protected abstract void setPasswordEntryInputEnabled(boolean enabled);
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index e3ac0f6..12c9fc9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -243,8 +243,8 @@
     }
 
     @Override
-    protected byte[] getPasswordText() {
-        return charSequenceToByteArray(mPasswordEntry.getText());
+    protected CharSequence getPasswordText() {
+        return mPasswordEntry.getText();
     }
 
     @Override
@@ -379,18 +379,4 @@
         return getContext().getString(
                 com.android.internal.R.string.keyguard_accessibility_password_unlock);
     }
-
-    /*
-     * This method avoids creating a new string when getting a byte array from EditView#getText().
-     */
-    private static byte[] charSequenceToByteArray(CharSequence chars) {
-        if (chars == null) {
-            return null;
-        }
-        byte[] bytes = new byte[chars.length()];
-        for (int i = 0; i < chars.length(); i++) {
-            bytes[i] = (byte) chars.charAt(i);
-        }
-        return bytes;
-    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 297052f..9eb168a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -39,6 +39,7 @@
 import com.android.internal.widget.LockPatternChecker;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockPatternView;
+import com.android.internal.widget.LockscreenCredential;
 import com.android.settingslib.animation.AppearAnimationCreator;
 import com.android.settingslib.animation.AppearAnimationUtils;
 import com.android.settingslib.animation.DisappearAnimationUtils;
@@ -297,9 +298,9 @@
                 LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL);
                 LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL_UNLOCKED);
             }
-            mPendingLockCheck = LockPatternChecker.checkPattern(
+            mPendingLockCheck = LockPatternChecker.checkCredential(
                     mLockPatternUtils,
-                    pattern,
+                    LockscreenCredential.createPattern(pattern),
                     userId,
                     new LockPatternChecker.OnCheckCallback() {
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 274f739..8e9df55 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -167,8 +167,8 @@
     }
 
     @Override
-    protected byte[] getPasswordText() {
-        return charSequenceToByteArray(mPasswordEntry.getText());
+    protected CharSequence getPasswordText() {
+        return mPasswordEntry.getText();
     }
 
     @Override
@@ -266,18 +266,4 @@
         return getContext().getString(
                 com.android.internal.R.string.keyguard_accessibility_pin_unlock);
     }
-
-    /*
-     * This method avoids creating a new string when getting a byte array from EditView#getText().
-     */
-    private static byte[] charSequenceToByteArray(CharSequence chars) {
-        if (chars == null) {
-            return null;
-        }
-        byte[] bytes = new byte[chars.length()];
-        for (int i = 0; i < chars.length(); i++) {
-            bytes[i] = (byte) chars.charAt(i);
-        }
-        return bytes;
-    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index af4e61b..5d35169 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -31,6 +31,7 @@
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
+import android.graphics.text.LineBreaker;
 import android.net.Uri;
 import android.os.Trace;
 import android.provider.Settings;
@@ -152,6 +153,7 @@
         mRowWithHeaderTextSize = mContext.getResources().getDimensionPixelSize(
                 R.dimen.header_row_font_size);
         mTitle.setOnClickListener(this);
+        mTitle.setBreakStrategy(LineBreaker.BREAK_STRATEGY_BALANCED);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 07bfa71..ff8a932 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -17,6 +17,7 @@
 import android.annotation.Nullable;
 import android.app.AlarmManager;
 import android.app.INotificationManager;
+import android.app.IWallpaperManager;
 import android.content.res.Configuration;
 import android.hardware.SensorPrivacyManager;
 import android.hardware.display.NightDisplayListener;
@@ -77,6 +78,7 @@
 import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.phone.AutoHideController;
+import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 import com.android.systemui.statusbar.phone.LightBarController;
 import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
@@ -318,6 +320,8 @@
     @Inject Lazy<SysUiState> mSysUiStateFlagsContainer;
     @Inject Lazy<AlarmManager> mAlarmManager;
     @Inject Lazy<KeyguardSecurityModel> mKeyguardSecurityModel;
+    @Inject Lazy<DozeParameters> mDozeParameters;
+    @Inject Lazy<IWallpaperManager> mWallpaperManager;
 
     @Inject
     public Dependency() {
@@ -504,6 +508,8 @@
         mProviders.put(SysUiState.class, mSysUiStateFlagsContainer::get);
         mProviders.put(AlarmManager.class, mAlarmManager::get);
         mProviders.put(KeyguardSecurityModel.class, mKeyguardSecurityModel::get);
+        mProviders.put(DozeParameters.class, mDozeParameters::get);
+        mProviders.put(IWallpaperManager.class, mWallpaperManager::get);
 
         // TODO(b/118592525): to support multi-display , we start to add something which is
         //                    per-display, while others may be global. I think it's time to add
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
index cf199c5..9192eed 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
@@ -22,26 +22,36 @@
 import static com.android.systemui.Dependency.MAIN_LOOPER_NAME;
 import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
 
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
 import android.annotation.Nullable;
+import android.app.ActivityManager;
 import android.app.AlarmManager;
+import android.app.IActivityManager;
 import android.app.INotificationManager;
+import android.app.IWallpaperManager;
 import android.content.Context;
+import android.content.res.Resources;
 import android.hardware.SensorPrivacyManager;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.hardware.display.NightDisplayListener;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.PowerManager;
 import android.os.Process;
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.util.DisplayMetrics;
 import android.view.IWindowManager;
+import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.systemui.doze.AlwaysOnDisplayPolicy;
 import com.android.systemui.plugins.PluginInitializerImpl;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.plugins.PluginManagerImpl;
@@ -59,7 +69,11 @@
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.util.leak.LeakDetector;
 
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
 import javax.inject.Named;
+import javax.inject.Qualifier;
 import javax.inject.Singleton;
 
 import dagger.Module;
@@ -71,6 +85,12 @@
  */
 @Module
 public class DependencyProvider {
+    @Qualifier
+    @Documented
+    @Retention(RUNTIME)
+    public @interface MainResources {
+        // TODO: use attribute to get other, non-main resources?
+    }
 
     @Singleton
     @Provides
@@ -249,4 +269,48 @@
     public LockPatternUtils provideLockPatternUtils(Context context) {
         return new LockPatternUtils(context);
     }
+
+    /** */
+    @Provides
+    public AmbientDisplayConfiguration provideAmbientDispalyConfiguration(Context context) {
+        return new AmbientDisplayConfiguration(context);
+    }
+
+    /** */
+    @Provides
+    public AlwaysOnDisplayPolicy provideAlwaysOnDisplayPolicy(Context context) {
+        return new AlwaysOnDisplayPolicy(context);
+    }
+
+    /** */
+    @Provides
+    public PowerManager providePowerManager(Context context) {
+        return context.getSystemService(PowerManager.class);
+    }
+
+    /** */
+    @Provides
+    @MainResources
+    public Resources provideResources(Context context) {
+        return context.getResources();
+    }
+
+    /** */
+    @Provides
+    public IWallpaperManager provideWallPaperManager() {
+        return IWallpaperManager.Stub.asInterface(
+                ServiceManager.getService(Context.WALLPAPER_SERVICE));
+    }
+
+    /** */
+    @Provides
+    public WindowManager providesWindowManager(Context context) {
+        return context.getSystemService(WindowManager.class);
+    }
+
+    /** */
+    @Provides
+    public IActivityManager providesIActivityManager() {
+        return ActivityManager.getService();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
index 5c561e5..362014f 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
@@ -50,13 +50,13 @@
 
     @Override
     public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
-        if ((entry.notification.getNotification().flags
+        if ((entry.getSbn().getNotification().flags
                 & Notification.FLAG_FOREGROUND_SERVICE) == 0) {
             return false;
         }
 
         long currentTime = System.currentTimeMillis();
-        return currentTime - entry.notification.getPostTime() < MIN_FGS_TIME_MS;
+        return currentTime - entry.getSbn().getPostTime() < MIN_FGS_TIME_MS;
     }
 
     @Override
@@ -79,12 +79,12 @@
             if (mManagedEntries.contains(entry)) {
                 mManagedEntries.remove(entry);
                 if (mNotificationSafeToRemoveCallback != null) {
-                    mNotificationSafeToRemoveCallback.onSafeToRemove(entry.key);
+                    mNotificationSafeToRemoveCallback.onSafeToRemove(entry.getKey());
                 }
             }
         };
         long delayAmt = MIN_FGS_TIME_MS
-                - (System.currentTimeMillis() - entry.notification.getPostTime());
+                - (System.currentTimeMillis() - entry.getSbn().getPostTime());
         mHandler.postDelayed(r, delayAmt);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index f9d8771..4a3b6df 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -50,12 +50,12 @@
         notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
             @Override
             public void onPendingEntryAdded(NotificationEntry entry) {
-                addNotification(entry.notification, entry.getImportance());
+                addNotification(entry.getSbn(), entry.getImportance());
             }
 
             @Override
             public void onPostEntryUpdated(NotificationEntry entry) {
-                updateNotification(entry.notification, entry.getImportance());
+                updateNotification(entry.getSbn(), entry.getImportance());
             }
 
             @Override
@@ -63,7 +63,7 @@
                     NotificationEntry entry,
                     NotificationVisibility visibility,
                     boolean removedByUser) {
-                removeNotification(entry.notification);
+                removeNotification(entry.getSbn());
             }
         });
 
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 1c0e0b3..29a7167 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -38,6 +38,8 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
+import javax.inject.Inject;
+
 /**
  * Default built-in wallpaper that simply shows a static image.
  */
@@ -50,8 +52,15 @@
     private static final int INTERVAL_WAIT_FOR_RENDERING = 100;
     private static final int PATIENCE_WAIT_FOR_RENDERING = 10;
     private static final boolean DEBUG = true;
+    private final DozeParameters mDozeParameters;
     private HandlerThread mWorker;
 
+    @Inject
+    public ImageWallpaper(DozeParameters dozeParameters) {
+        super();
+        mDozeParameters = dozeParameters;
+    }
+
     @Override
     public void onCreate() {
         super.onCreate();
@@ -61,7 +70,7 @@
 
     @Override
     public Engine onCreateEngine() {
-        return new GLEngine(this);
+        return new GLEngine(this, mDozeParameters);
     }
 
     @Override
@@ -89,9 +98,9 @@
         // This variable can only be accessed in synchronized block.
         private boolean mWaitingForRendering;
 
-        GLEngine(Context context) {
+        GLEngine(Context context, DozeParameters dozeParameters) {
             mNeedTransition = ActivityManager.isHighEndGfx()
-                    && !DozeParameters.getInstance(context).getDisplayNeedsBlanking();
+                    && !dozeParameters.getDisplayNeedsBlanking();
 
             // We will preserve EGL context when we are in lock screen or aod
             // to avoid janking in following transition, we need to release when back to home.
@@ -339,9 +348,9 @@
             boolean isHighEndGfx = ActivityManager.isHighEndGfx();
             out.print(prefix); out.print("isHighEndGfx="); out.println(isHighEndGfx);
 
-            DozeParameters dozeParameters = DozeParameters.getInstance(getApplicationContext());
             out.print(prefix); out.print("displayNeedsBlanking=");
-            out.println(dozeParameters != null ? dozeParameters.getDisplayNeedsBlanking() : "null");
+            out.println(
+                    mDozeParameters != null ? mDozeParameters.getDisplayNeedsBlanking() : "null");
 
             out.print(prefix); out.print("mNeedTransition="); out.println(mNeedTransition);
             out.print(prefix); out.print("StatusBarState=");
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 3a7a7f7..ad20986 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -460,7 +460,7 @@
                         | WindowManager.LayoutParams.FLAG_SLIPPERY
                         | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
                 PixelFormat.TRANSLUCENT);
-        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS
+        lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS
                 | WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
 
         if (!DEBUG_SCREENSHOT_ROUNDED_CORNERS) {
diff --git a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java b/packages/SystemUI/src/com/android/systemui/ServiceBinder.java
index e61268e..c11236e 100644
--- a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/ServiceBinder.java
@@ -40,6 +40,12 @@
     /** */
     @Binds
     @IntoMap
+    @ClassKey(ImageWallpaper.class)
+    public abstract Service bindImageWallpaper(ImageWallpaper service);
+
+    /** */
+    @Binds
+    @IntoMap
     @ClassKey(KeyguardService.class)
     public abstract Service bindKeyguardService(KeyguardService service);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java b/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java
index a8591bb..10009f5 100644
--- a/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java
@@ -203,7 +203,7 @@
             mWinParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                     | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
             mWinParams.format = PixelFormat.TRANSLUCENT;
-            mWinParams.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+            mWinParams.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
             mWinParams.setTitle(SizeCompatModeActivityController.class.getSimpleName()
                     + context.getDisplayId());
         }
diff --git a/packages/SystemUI/src/com/android/systemui/SysUIToast.java b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
index 8bcf057..0f7f1be 100644
--- a/packages/SystemUI/src/com/android/systemui/SysUIToast.java
+++ b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
@@ -31,7 +31,7 @@
     public static Toast makeText(Context context, CharSequence text, @Duration int duration) {
         Toast toast = Toast.makeText(context, text, duration);
         toast.getWindowParams().privateFlags |=
-                WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+                WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         return toast;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 189e511..91776a3 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -237,7 +237,7 @@
                                 if (statusBar != null) {
                                     plugin.setup(statusBar.getStatusBarWindow(),
                                             statusBar.getNavigationBarView(), new Callback(plugin),
-                                            DozeParameters.getInstance(getBaseContext()));
+                                            Dependency.get(DozeParameters.class));
                                 }
                             }
                         });
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index da4f304..ef7526b 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -160,7 +160,8 @@
             StatusBarStateController statusBarStateController) {
         return new NotificationIconAreaController(context, statusBar, statusBarStateController,
                 wakeUpCoordinator, keyguardBypassController,
-                Dependency.get(NotificationMediaManager.class));
+                Dependency.get(NotificationMediaManager.class),
+                Dependency.get(DozeParameters.class));
     }
 
     public KeyguardIndicationController createKeyguardIndicationController(Context context,
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
index 739eade..6f5a17d 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
@@ -21,6 +21,7 @@
 import android.os.HandlerThread;
 import android.os.SystemClock;
 
+import androidx.annotation.Nullable;
 import androidx.slice.Clock;
 
 import com.android.internal.app.AssistUtils;
@@ -68,6 +69,7 @@
     }
 
     @Provides
+    @Nullable
     static AssistHandleViewController provideAssistHandleViewController(
             NavigationBarController navigationBarController) {
         return navigationBarController.getAssistHandlerViewController();
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
index 9958124..4cb1708 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
@@ -164,8 +164,11 @@
     }
 
     private void updateAssistHandleVisibility() {
-        AssistHandleViewController controller = Dependency.get(NavigationBarController.class)
-                .getAssistHandlerViewController();
+        NavigationBarController navigationBarController =
+                Dependency.get(NavigationBarController.class);
+        AssistHandleViewController controller =
+                navigationBarController == null
+                        ? null : navigationBarController.getAssistHandlerViewController();
         if (controller != null) {
             controller.setAssistHintBlocked(mInvocationInProgress);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index a9359d4..f1abdb3 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -580,7 +580,7 @@
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                 PixelFormat.TRANSLUCENT);
-        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+        lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         lp.setTitle("BiometricPrompt");
         lp.token = windowToken;
         return lp;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
index 8df072e..bebaa4b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
@@ -26,7 +26,7 @@
 import android.widget.TextView;
 
 import com.android.internal.widget.LockPatternChecker;
-import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockscreenCredential;
 import com.android.systemui.R;
 
 /**
@@ -96,13 +96,16 @@
     }
 
     private void checkPasswordAndUnlock() {
-        final byte[] password = LockPatternUtils.charSequenceToByteArray(mPasswordField.getText());
-        if (password == null || password.length == 0) {
-            return;
-        }
+        try (LockscreenCredential password =  mCredentialType == Utils.CREDENTIAL_PIN
+                ? LockscreenCredential.createPinOrNone(mPasswordField.getText())
+                : LockscreenCredential.createPasswordOrNone(mPasswordField.getText())) {
+            if (password.isNone()) {
+                return;
+            }
 
-        mPendingLockCheck = LockPatternChecker.checkPassword(mLockPatternUtils,
-                password, mUserId, this::onCredentialChecked);
+            mPendingLockCheck = LockPatternChecker.checkCredential(mLockPatternUtils,
+                    password, mUserId, this::onCredentialChecked);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java
index 6c36f82..14414a4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java
@@ -22,6 +22,7 @@
 import com.android.internal.widget.LockPatternChecker;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockPatternView;
+import com.android.internal.widget.LockscreenCredential;
 import com.android.systemui.R;
 
 import java.util.List;
@@ -64,11 +65,13 @@
                 return;
             }
 
-            mPendingLockCheck = LockPatternChecker.checkPattern(
-                    mLockPatternUtils,
-                    pattern,
-                    mUserId,
-                    this::onPatternChecked);
+            try (LockscreenCredential credential = LockscreenCredential.createPattern(pattern)) {
+                mPendingLockCheck = LockPatternChecker.checkCredential(
+                        mLockPatternUtils,
+                        credential,
+                        mUserId,
+                        this::onPatternChecked);
+            }
         }
 
         private void onPatternChecked(boolean matched, int timeoutMs) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index c3cee35..7600b2f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -83,23 +83,23 @@
     private boolean mSuppressFlyout;
 
     public static String groupId(NotificationEntry entry) {
-        UserHandle user = entry.notification.getUser();
-        return user.getIdentifier() + "|" + entry.notification.getPackageName();
+        UserHandle user = entry.getSbn().getUser();
+        return user.getIdentifier() + "|" + entry.getSbn().getPackageName();
     }
 
     /** Used in tests when no UI is required. */
     @VisibleForTesting(visibility = PRIVATE)
     Bubble(Context context, NotificationEntry e) {
         mEntry = e;
-        mKey = e.key;
-        mLastUpdated = e.notification.getPostTime();
+        mKey = e.getKey();
+        mLastUpdated = e.getSbn().getPostTime();
         mGroupId = groupId(e);
 
         PackageManager pm = context.getPackageManager();
         ApplicationInfo info;
         try {
             info = pm.getApplicationInfo(
-                mEntry.notification.getPackageName(),
+                mEntry.getSbn().getPackageName(),
                 PackageManager.MATCH_UNINSTALLED_PACKAGES
                     | PackageManager.MATCH_DISABLED_COMPONENTS
                     | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
@@ -107,10 +107,10 @@
             if (info != null) {
                 mAppName = String.valueOf(pm.getApplicationLabel(info));
             }
-            Drawable appIcon = pm.getApplicationIcon(mEntry.notification.getPackageName());
-            mUserBadgedAppIcon = pm.getUserBadgedIcon(appIcon, mEntry.notification.getUser());
+            Drawable appIcon = pm.getApplicationIcon(mEntry.getSbn().getPackageName());
+            mUserBadgedAppIcon = pm.getUserBadgedIcon(appIcon, mEntry.getSbn().getUser());
         } catch (PackageManager.NameNotFoundException unused) {
-            mAppName = mEntry.notification.getPackageName();
+            mAppName = mEntry.getSbn().getPackageName();
         }
     }
 
@@ -127,7 +127,7 @@
     }
 
     public String getPackageName() {
-        return mEntry.notification.getPackageName();
+        return mEntry.getSbn().getPackageName();
     }
 
     public String getAppName() {
@@ -190,7 +190,7 @@
 
     void updateEntry(NotificationEntry entry) {
         mEntry = entry;
-        mLastUpdated = entry.notification.getPostTime();
+        mLastUpdated = entry.getSbn().getPostTime();
         if (mInflated) {
             mIconView.update(this);
             mExpandedView.update(this);
@@ -287,7 +287,7 @@
      * is an ongoing bubble.
      */
     boolean isOngoing() {
-        int flags = mEntry.notification.getNotification().flags;
+        int flags = mEntry.getSbn().getNotification().flags;
         return (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
     }
 
@@ -296,8 +296,8 @@
         boolean useRes = data.getDesiredHeightResId() != 0;
         if (useRes) {
             return getDimenForPackageUser(context, data.getDesiredHeightResId(),
-                    mEntry.notification.getPackageName(),
-                    mEntry.notification.getUser().getIdentifier());
+                    mEntry.getSbn().getPackageName(),
+                    mEntry.getSbn().getUser().getIdentifier());
         } else {
             return data.getDesiredHeight()
                     * context.getResources().getDisplayMetrics().density;
@@ -316,7 +316,7 @@
 
     @Nullable
     PendingIntent getBubbleIntent(Context context) {
-        Notification notif = mEntry.notification.getNotification();
+        Notification notif = mEntry.getSbn().getNotification();
         Notification.BubbleMetadata data = notif.getBubbleMetadata();
         if (BubbleController.canLaunchInActivityView(context, mEntry) && data != null) {
             return data.getIntent();
@@ -327,7 +327,7 @@
     Intent getSettingsIntent() {
         final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS);
         intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
-        intent.putExtra(Settings.EXTRA_APP_UID, mEntry.notification.getUid());
+        intent.putExtra(Settings.EXTRA_APP_UID, mEntry.getSbn().getUid());
         intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
@@ -339,7 +339,7 @@
      * notification, based on its type. Returns null if there should not be an update message.
      */
     CharSequence getUpdateMessage(Context context) {
-        final Notification underlyingNotif = mEntry.notification.getNotification();
+        final Notification underlyingNotif = mEntry.getSbn().getNotification();
         final Class<? extends Notification.Style> style = underlyingNotif.getNotificationStyle();
 
         try {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 9568a18..0231b56 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -262,7 +262,7 @@
                         // More notifications could be added causing summary to no longer
                         // be suppressed -- in this case need to remove the key.
                         final String groupKey = group.summary != null
-                                ? group.summary.notification.getGroupKey()
+                                ? group.summary.getSbn().getGroupKey()
                                 : null;
                         if (!suppressed && groupKey != null
                                 && mBubbleData.isSummarySuppressed(groupKey)) {
@@ -346,7 +346,7 @@
             return;
         }
         for (NotificationEntry e : notificationData.getNotificationsForCurrentUser()) {
-            if (savedBubbleKeys.contains(e.key)
+            if (savedBubbleKeys.contains(e.getKey())
                     && mNotificationInterruptionStateProvider.shouldBubbleUp(e)
                     && canLaunchInActivityView(mContext, e)) {
                 updateBubble(e, /* suppressFlyout= */ true);
@@ -445,7 +445,7 @@
         boolean isBubbleAndSuppressed = mBubbleData.hasBubbleWithKey(key)
                 && !mBubbleData.getBubbleWithKey(key).showInShadeWhenBubble();
         NotificationEntry entry = mNotificationEntryManager.getNotificationData().get(key);
-        String groupKey = entry != null ? entry.notification.getGroupKey() : null;
+        String groupKey = entry != null ? entry.getSbn().getGroupKey() : null;
         boolean isSuppressedSummary = mBubbleData.isSummarySuppressed(groupKey);
         boolean isSummary = key.equals(mBubbleData.getSummaryKey(groupKey));
         return (isSummary && isSuppressedSummary) || isBubbleAndSuppressed;
@@ -528,14 +528,14 @@
             @Override
             public boolean onNotificationRemoveRequested(String key, int reason) {
                 NotificationEntry entry = mNotificationEntryManager.getNotificationData().get(key);
-                String groupKey = entry != null ? entry.notification.getGroupKey() : null;
+                String groupKey = entry != null ? entry.getSbn().getGroupKey() : null;
                 ArrayList<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey);
 
                 boolean inBubbleData = mBubbleData.hasBubbleWithKey(key);
                 boolean isSuppressedSummary = (mBubbleData.isSummarySuppressed(groupKey)
                         && mBubbleData.getSummaryKey(groupKey).equals(key));
                 boolean isSummary = entry != null
-                        && entry.notification.getNotification().isGroupSummary();
+                        && entry.getSbn().getNotification().isGroupSummary();
                 boolean isSummaryOfBubbles = (isSuppressedSummary || isSummary)
                         && bubbleChildren != null && !bubbleChildren.isEmpty();
 
@@ -566,7 +566,7 @@
                     bubble.setShowInShadeWhenBubble(false);
                     bubble.setShowBubbleDot(false);
                     if (mStackView != null) {
-                        mStackView.updateDotVisibility(entry.key);
+                        mStackView.updateDotVisibility(entry.getKey());
                     }
                     mNotificationEntryManager.updateNotifications(
                             "BubbleController.onNotificationRemoveRequested");
@@ -582,7 +582,7 @@
 
     private boolean handleSummaryRemovalInterception(NotificationEntry summary,
             boolean userRemovedNotif) {
-        String groupKey = summary.notification.getGroupKey();
+        String groupKey = summary.getSbn().getGroupKey();
         ArrayList<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey);
 
         if (userRemovedNotif) {
@@ -603,11 +603,11 @@
 
             // If the summary was auto-generated we don't need to keep that notification around
             // because apps can't cancel it; so we only intercept & suppress real summaries.
-            boolean isAutogroupSummary = (summary.notification.getNotification().flags
+            boolean isAutogroupSummary = (summary.getSbn().getNotification().flags
                     & FLAG_AUTOGROUP_SUMMARY) != 0;
             if (!isAutogroupSummary) {
-                mBubbleData.addSummaryToSuppress(summary.notification.getGroupKey(),
-                        summary.key);
+                mBubbleData.addSummaryToSuppress(summary.getSbn().getGroupKey(),
+                        summary.getKey());
                 // Tell shade to update for the suppression
                 mNotificationEntryManager.updateNotifications(
                         "BubbleController.handleSummaryRemovalInterception");
@@ -641,11 +641,11 @@
         public void onPreEntryUpdated(NotificationEntry entry) {
             boolean shouldBubble = mNotificationInterruptionStateProvider.shouldBubbleUp(entry)
                     && canLaunchInActivityView(mContext, entry);
-            if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.key)) {
+            if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.getKey())) {
                 // It was previously a bubble but no longer a bubble -- lets remove it
-                removeBubble(entry.key, DISMISS_NO_LONGER_BUBBLE);
+                removeBubble(entry.getKey(), DISMISS_NO_LONGER_BUBBLE);
             } else if (shouldBubble) {
-                Bubble b = mBubbleData.getBubbleWithKey(entry.key);
+                Bubble b = mBubbleData.getBubbleWithKey(entry.getKey());
                 updateBubble(entry);
             }
         }
@@ -695,10 +695,10 @@
                             && !bubble.showInShadeWhenBubble()) {
                         // The bubble is gone & the notification is gone, time to actually remove it
                         mNotificationEntryManager.performRemoveNotification(
-                                bubble.getEntry().notification, UNDEFINED_DISMISS_REASON);
+                                bubble.getEntry().getSbn(), UNDEFINED_DISMISS_REASON);
                     } else {
                         // Update the flag for SysUI
-                        bubble.getEntry().notification.getNotification().flags &= ~FLAG_BUBBLE;
+                        bubble.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
 
                         // Make sure NoMan knows it's not a bubble anymore so anyone querying it
                         // will get right result back
@@ -712,7 +712,7 @@
 
                     // Check if removed bubble has an associated suppressed group summary that needs
                     // to be removed now.
-                    final String groupKey = bubble.getEntry().notification.getGroupKey();
+                    final String groupKey = bubble.getEntry().getSbn().getGroupKey();
                     if (mBubbleData.isSummarySuppressed(groupKey)
                             && mBubbleData.getBubblesInGroup(groupKey).isEmpty()) {
                         // Time to actually remove the summary.
@@ -721,20 +721,21 @@
                         NotificationEntry entry =
                                 mNotificationEntryManager.getNotificationData().get(notifKey);
                         mNotificationEntryManager.performRemoveNotification(
-                                entry.notification, UNDEFINED_DISMISS_REASON);
+                                entry.getSbn(), UNDEFINED_DISMISS_REASON);
                     }
 
                     // Check if summary should be removed from NoManGroup
                     NotificationEntry summary = mNotificationGroupManager.getLogicalGroupSummary(
-                            bubble.getEntry().notification);
+                            bubble.getEntry().getSbn());
                     if (summary != null) {
                         ArrayList<NotificationEntry> summaryChildren =
-                                mNotificationGroupManager.getLogicalChildren(summary.notification);
-                        boolean isSummaryThisNotif = summary.key.equals(bubble.getEntry().key);
+                                mNotificationGroupManager.getLogicalChildren(summary.getSbn());
+                        boolean isSummaryThisNotif = summary.getKey().equals(
+                                bubble.getEntry().getKey());
                         if (!isSummaryThisNotif
                                 && (summaryChildren == null || summaryChildren.isEmpty())) {
                             mNotificationEntryManager.performRemoveNotification(
-                                    summary.notification, UNDEFINED_DISMISS_REASON);
+                                    summary.getSbn(), UNDEFINED_DISMISS_REASON);
                         }
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index d43e030..2f7f47b6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -183,7 +183,7 @@
         if (DEBUG_BUBBLE_DATA) {
             Log.d(TAG, "notificationEntryUpdated: " + entry);
         }
-        Bubble bubble = getBubbleWithKey(entry.key);
+        Bubble bubble = getBubbleWithKey(entry.getKey());
         suppressFlyout = !entry.isVisuallyInterruptive || suppressFlyout;
 
         if (bubble == null) {
@@ -217,7 +217,7 @@
         if (DEBUG_BUBBLE_DATA) {
             Log.d(TAG, "notificationEntryRemoved: entry=" + entry + " reason=" + reason);
         }
-        doRemove(entry.key, reason);
+        doRemove(entry.getKey(), reason);
         dispatchPendingChanges();
     }
 
@@ -290,7 +290,7 @@
             return bubbleChildren;
         }
         for (Bubble b : mBubbles) {
-            if (groupKey.equals(b.getEntry().notification.getGroupKey())) {
+            if (groupKey.equals(b.getEntry().getSbn().getGroupKey())) {
                 bubbleChildren.add(b);
             }
         }
@@ -633,7 +633,8 @@
                 try {
                     deleteIntent.send();
                 } catch (PendingIntent.CanceledException e) {
-                    Log.w(TAG, "Failed to send delete intent for bubble with key: " + entry.key);
+                    Log.w(TAG, "Failed to send delete intent for bubble with key: "
+                            + entry.getKey());
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 6f953d5..1d9f6b2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -501,7 +501,7 @@
         if (id == R.id.settings_button) {
             Intent intent = mBubble.getSettingsIntent();
             mStackView.collapseStack(() -> {
-                mContext.startActivityAsUser(intent, mBubble.getEntry().notification.getUser());
+                mContext.startActivityAsUser(intent, mBubble.getEntry().getSbn().getUser());
                 logBubbleClickEvent(mBubble,
                         StatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_SETTINGS);
             });
@@ -609,7 +609,7 @@
      * @param action the user interaction enum.
      */
     private void logBubbleClickEvent(Bubble bubble, int action) {
-        StatusBarNotification notification = bubble.getEntry().notification;
+        StatusBarNotification notification = bubble.getEntry().getSbn();
         StatsLog.write(StatsLog.BUBBLE_UI_CHANGED,
                 notification.getPackageName(),
                 notification.getNotification().getChannelId(),
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 340dced..e5af389 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -629,7 +629,7 @@
         }
         Bubble topBubble = mBubbleData.getBubbles().get(0);
         String appName = topBubble.getAppName();
-        Notification notification = topBubble.getEntry().notification.getNotification();
+        Notification notification = topBubble.getEntry().getSbn().getNotification();
         CharSequence titleCharSeq = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
         String titleStr = getResources().getString(R.string.stream_notification);
         if (titleCharSeq != null) {
@@ -1681,7 +1681,7 @@
      */
     private void logBubbleEvent(@Nullable Bubble bubble, int action) {
         if (bubble == null || bubble.getEntry() == null
-                || bubble.getEntry().notification == null) {
+                || bubble.getEntry().getSbn() == null) {
             StatsLog.write(StatsLog.BUBBLE_UI_CHANGED,
                     null /* package name */,
                     null /* notification channel */,
@@ -1695,7 +1695,7 @@
                     false /* on-going bubble */,
                     false /* isAppForeground (unused) */);
         } else {
-            StatusBarNotification notification = bubble.getEntry().notification;
+            StatusBarNotification notification = bubble.getEntry().getSbn();
             StatsLog.write(StatsLog.BUBBLE_UI_CHANGED,
                     notification.getPackageName(),
                     notification.getNotification().getChannelId(),
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
index 4512aa8..780c314 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
@@ -230,7 +230,7 @@
         }
         // Update icon.
         Notification.BubbleMetadata metadata = mBubble.getEntry().getBubbleMetadata();
-        Notification n = mBubble.getEntry().notification.getNotification();
+        Notification n = mBubble.getEntry().getSbn().getNotification();
         Icon ic = metadata.getIcon();
         boolean needsTint = ic.getType() != Icon.TYPE_ADAPTIVE_BITMAP;
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/PointerCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/PointerCountClassifier.java
index 85a4d23..b726c3e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/PointerCountClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/PointerCountClassifier.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.classifier.brightline;
 
+import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN;
+import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
+
 import android.view.MotionEvent;
 
 import java.util.Locale;
@@ -29,6 +32,7 @@
 class PointerCountClassifier extends FalsingClassifier {
 
     private static final int MAX_ALLOWED_POINTERS = 1;
+    private static final int MAX_ALLOWED_POINTERS_SWIPE_DOWN = 2;
     private int mMaxPointerCount;
 
     PointerCountClassifier(FalsingDataProvider dataProvider) {
@@ -50,6 +54,10 @@
 
     @Override
     public boolean isFalseTouch() {
+        int interactionType = getInteractionType();
+        if (interactionType == QUICK_SETTINGS || interactionType == NOTIFICATION_DRAG_DOWN) {
+            return mMaxPointerCount > MAX_ALLOWED_POINTERS_SWIPE_DOWN;
+        }
         return mMaxPointerCount > MAX_ALLOWED_POINTERS;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index ca4ec6d..705147f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -18,6 +18,7 @@
 
 import android.app.AlarmManager;
 import android.app.Application;
+import android.app.IWallpaperManager;
 import android.content.Context;
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
@@ -25,7 +26,6 @@
 import android.os.Handler;
 
 import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SystemUIApplication;
 import com.android.systemui.dock.DockManager;
@@ -39,47 +39,74 @@
 import com.android.systemui.util.wakelock.DelayedWakeLock;
 import com.android.systemui.util.wakelock.WakeLock;
 
+import javax.inject.Inject;
+
 public class DozeFactory {
 
-    public DozeFactory() {
+    private final FalsingManager mFalsingManager;
+    private final DozeLog mDozeLog;
+    private final DozeParameters mDozeParameters;
+    private final BatteryController mBatteryController;
+    private final AsyncSensorManager mAsyncSensorManager;
+    private final AlarmManager mAlarmManager;
+    private final WakefulnessLifecycle mWakefulnessLifecycle;
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private final DockManager mDockManager;
+    private final IWallpaperManager mWallpaperManager;
+    private final ProximitySensor mProximitySensor;
+
+    @Inject
+    public DozeFactory(FalsingManager falsingManager, DozeLog dozeLog,
+            DozeParameters dozeParameters, BatteryController batteryController,
+            AsyncSensorManager asyncSensorManager, AlarmManager alarmManager,
+            WakefulnessLifecycle wakefulnessLifecycle, KeyguardUpdateMonitor keyguardUpdateMonitor,
+            DockManager dockManager, IWallpaperManager wallpaperManager,
+            ProximitySensor proximitySensor) {
+        mFalsingManager = falsingManager;
+        mDozeLog = dozeLog;
+        mDozeParameters = dozeParameters;
+        mBatteryController = batteryController;
+        mAsyncSensorManager = asyncSensorManager;
+        mAlarmManager = alarmManager;
+        mWakefulnessLifecycle = wakefulnessLifecycle;
+        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+        mDockManager = dockManager;
+        mWallpaperManager = wallpaperManager;
+        mProximitySensor = proximitySensor;
     }
 
     /** Creates a DozeMachine with its parts for {@code dozeService}. */
-    public DozeMachine assembleMachine(DozeService dozeService, FalsingManager falsingManager,
-            DozeLog dozeLog) {
-        Context context = dozeService;
-        AsyncSensorManager sensorManager = Dependency.get(AsyncSensorManager.class);
-        AlarmManager alarmManager = context.getSystemService(AlarmManager.class);
-        DockManager dockManager = Dependency.get(DockManager.class);
-        WakefulnessLifecycle wakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
-
+    public DozeMachine assembleMachine(DozeService dozeService) {
         DozeHost host = getHost(dozeService);
-        AmbientDisplayConfiguration config = new AmbientDisplayConfiguration(context);
-        DozeParameters params = DozeParameters.getInstance(context);
+        AmbientDisplayConfiguration config = new AmbientDisplayConfiguration(dozeService);
         Handler handler = new Handler();
         WakeLock wakeLock = new DelayedWakeLock(handler,
-                WakeLock.createPartial(context, "Doze"));
+                WakeLock.createPartial(dozeService, "Doze"));
 
         DozeMachine.Service wrappedService = dozeService;
         wrappedService = new DozeBrightnessHostForwarder(wrappedService, host);
-        wrappedService = DozeScreenStatePreventingAdapter.wrapIfNeeded(wrappedService, params);
-        wrappedService = DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(wrappedService,
-                params);
+        wrappedService = DozeScreenStatePreventingAdapter.wrapIfNeeded(
+                wrappedService, mDozeParameters);
+        wrappedService = DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(
+                wrappedService, mDozeParameters);
 
         DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock,
-                wakefulnessLifecycle, Dependency.get(BatteryController.class), dozeLog);
+                                              mWakefulnessLifecycle, mBatteryController, mDozeLog);
         machine.setParts(new DozeMachine.Part[]{
-                new DozePauser(handler, machine, alarmManager, params.getPolicy()),
-                new DozeFalsingManagerAdapter(falsingManager),
-                createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
-                        handler, wakeLock, machine, dockManager, dozeLog),
-                createDozeUi(context, host, wakeLock, machine, handler, alarmManager, params,
-                        dozeLog),
-                new DozeScreenState(wrappedService, handler, params, wakeLock),
-                createDozeScreenBrightness(context, wrappedService, sensorManager, host, params,
-                        handler),
-                new DozeWallpaperState(context, getBiometricUnlockController(dozeService)),
-                new DozeDockHandler(context, machine, host, config, handler, dockManager),
+                new DozePauser(handler, machine, mAlarmManager, mDozeParameters.getPolicy()),
+                new DozeFalsingManagerAdapter(mFalsingManager),
+                createDozeTriggers(dozeService, mAsyncSensorManager, host, mAlarmManager, config,
+                        mDozeParameters, handler, wakeLock, machine, mDockManager, mDozeLog),
+                createDozeUi(dozeService, host, wakeLock, machine, handler, mAlarmManager,
+                        mDozeParameters, mDozeLog),
+                new DozeScreenState(wrappedService, handler, host, mDozeParameters, wakeLock),
+                createDozeScreenBrightness(dozeService, wrappedService, mAsyncSensorManager, host,
+                        mDozeParameters, handler),
+                new DozeWallpaperState(
+                        mWallpaperManager,
+                        getBiometricUnlockController(dozeService),
+                        mDozeParameters),
+                new DozeDockHandler(dozeService, machine, host, config, handler, mDockManager),
                 new DozeAuthRemover(dozeService)
         });
 
@@ -102,7 +129,7 @@
         boolean allowPulseTriggers = true;
         return new DozeTriggers(context, machine, host, alarmManager, config, params,
                 sensorManager, handler, wakeLock, allowPulseTriggers, dockManager,
-                new ProximitySensor(context, sensorManager), dozeLog);
+                mProximitySensor, dozeLog);
 
     }
 
@@ -110,7 +137,7 @@
             DozeMachine machine, Handler handler, AlarmManager alarmManager,
             DozeParameters params, DozeLog dozeLog) {
         return new DozeUi(context, alarmManager, machine, wakeLock, host, handler, params,
-                Dependency.get(KeyguardUpdateMonitor.class), dozeLog);
+                          mKeyguardUpdateMonitor, dozeLog);
     }
 
     public static DozeHost getHost(DozeService service) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index 07dd2cd..1a6bd60 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -63,9 +63,10 @@
     void setDozeScreenBrightness(int value);
 
     /**
-     * Makes scrims black and changes animation durations.
+     * Fade out screen before switching off the display power mode.
+     * @param onDisplayOffCallback Executed when the display is black.
      */
-    default void prepareForGentleWakeUp() {}
+    void prepareForGentleSleep(Runnable onDisplayOffCallback);
 
     void onIgnoreTouchWhilePulsing(boolean ignore);
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index 38ee2fe..95c42fc 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -16,6 +16,12 @@
 
 package com.android.systemui.doze;
 
+import static com.android.systemui.doze.DozeMachine.State.DOZE;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSING;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSE_DONE;
+
 import android.os.Handler;
 import android.util.Log;
 import android.view.Display;
@@ -48,21 +54,24 @@
     private final Handler mHandler;
     private final Runnable mApplyPendingScreenState = this::applyPendingScreenState;
     private final DozeParameters mParameters;
+    private final DozeHost mDozeHost;
 
     private int mPendingScreenState = Display.STATE_UNKNOWN;
     private SettableWakeLock mWakeLock;
 
-    public DozeScreenState(DozeMachine.Service service, Handler handler,
+    public DozeScreenState(DozeMachine.Service service, Handler handler, DozeHost host,
             DozeParameters parameters, WakeLock wakeLock) {
         mDozeService = service;
         mHandler = handler;
         mParameters = parameters;
+        mDozeHost = host;
         mWakeLock = new SettableWakeLock(wakeLock, TAG);
     }
 
     @Override
     public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
         int screenState = newState.screenState(mParameters);
+        mDozeHost.prepareForGentleSleep(null);
 
         if (newState == DozeMachine.State.FINISH) {
             // Make sure not to apply the screen state after DozeService was destroyed.
@@ -79,12 +88,13 @@
             return;
         }
 
-        boolean messagePending = mHandler.hasCallbacks(mApplyPendingScreenState);
-        boolean pulseEnding = oldState  == DozeMachine.State.DOZE_PULSE_DONE
-                && newState == DozeMachine.State.DOZE_AOD;
-        boolean turningOn = (oldState == DozeMachine.State.DOZE_AOD_PAUSED
-                || oldState  == DozeMachine.State.DOZE) && newState == DozeMachine.State.DOZE_AOD;
-        boolean justInitialized = oldState == DozeMachine.State.INITIALIZED;
+        final boolean messagePending = mHandler.hasCallbacks(mApplyPendingScreenState);
+        final boolean pulseEnding = oldState  == DOZE_PULSE_DONE && newState == DOZE_AOD;
+        final boolean turningOn = (oldState == DOZE_AOD_PAUSED
+                || oldState  == DOZE) && newState == DOZE_AOD;
+        final boolean turningOff = (oldState == DOZE_AOD && newState == DOZE)
+                || (oldState == DOZE_AOD_PAUSING && newState == DOZE_AOD_PAUSED);
+        final boolean justInitialized = oldState == DozeMachine.State.INITIALIZED;
         if (messagePending || justInitialized || pulseEnding || turningOn) {
             // During initialization, we hide the navigation bar. That is however only applied after
             // a traversal; setting the screen state here is immediate however, so it can happen
@@ -93,7 +103,7 @@
             mPendingScreenState = screenState;
 
             // Delay screen state transitions even longer while animations are running.
-            boolean shouldDelayTransition = newState == DozeMachine.State.DOZE_AOD
+            boolean shouldDelayTransition = newState == DOZE_AOD
                     && mParameters.shouldControlScreenOff() && !turningOn;
 
             if (shouldDelayTransition) {
@@ -114,6 +124,8 @@
             } else if (DEBUG) {
                 Log.d(TAG, "Pending display state change to " + screenState);
             }
+        } else if (turningOff) {
+            mDozeHost.prepareForGentleSleep(() -> applyScreenState(screenState));
         } else {
             applyScreenState(screenState);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 7d86028..05a234f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -153,7 +153,7 @@
                         dozeLog),
         };
 
-        mProximitySensor = new ProximitySensor(context, sensorManager);
+        mProximitySensor = new ProximitySensor(context.getResources(), sensorManager);
 
         mProximitySensor.register(
                 proximityEvent -> {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 17559c9..08734d2 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -22,10 +22,8 @@
 import android.service.dreams.DreamService;
 import android.util.Log;
 
-import com.android.systemui.Dependency;
 import com.android.systemui.plugins.DozeServicePlugin;
 import com.android.systemui.plugins.DozeServicePlugin.RequestDoze;
-import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.shared.plugins.PluginManager;
 
@@ -38,18 +36,17 @@
         implements DozeMachine.Service, RequestDoze, PluginListener<DozeServicePlugin> {
     private static final String TAG = "DozeService";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private final FalsingManager mFalsingManager;
-    private final DozeLog mDozeLog;
+    private final DozeFactory mDozeFactory;
 
     private DozeMachine mDozeMachine;
     private DozeServicePlugin mDozePlugin;
     private PluginManager mPluginManager;
 
     @Inject
-    public DozeService(FalsingManager falsingManager, DozeLog dozeLog) {
+    public DozeService(DozeFactory dozeFactory, PluginManager pluginManager) {
         setDebug(DEBUG);
-        mFalsingManager = falsingManager;
-        mDozeLog = dozeLog;
+        mDozeFactory = dozeFactory;
+        mPluginManager = pluginManager;
     }
 
     @Override
@@ -62,9 +59,8 @@
             finish();
             return;
         }
-        mPluginManager = Dependency.get(PluginManager.class);
         mPluginManager.addPluginListener(this, DozeServicePlugin.class, false /* allowMultiple */);
-        mDozeMachine = new DozeFactory().assembleMachine(this, mFalsingManager, mDozeLog);
+        mDozeMachine = mDozeFactory.assembleMachine(this);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 2c0ccd21..f155783 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -135,7 +135,6 @@
                 break;
             case DOZE:
             case DOZE_AOD_PAUSED:
-                mHost.prepareForGentleWakeUp();
                 unscheduleTimeTick();
                 break;
             case DOZE_REQUEST_PULSE:
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
index 35c8b74..9457dc9 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
@@ -17,12 +17,9 @@
 package com.android.systemui.doze;
 
 import android.app.IWallpaperManager;
-import android.content.Context;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.util.Log;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.BiometricUnlockController;
 import com.android.systemui.statusbar.phone.DozeParameters;
@@ -42,17 +39,10 @@
     private final BiometricUnlockController mBiometricUnlockController;
     private boolean mIsAmbientMode;
 
-    public DozeWallpaperState(Context context,
-            BiometricUnlockController biometricUnlockController) {
-        this(IWallpaperManager.Stub.asInterface(
-                ServiceManager.getService(Context.WALLPAPER_SERVICE)),
-                biometricUnlockController,
-                DozeParameters.getInstance(context));
-    }
-
-    @VisibleForTesting
-    DozeWallpaperState(IWallpaperManager wallpaperManagerService,
-            BiometricUnlockController biometricUnlockController, DozeParameters parameters) {
+    public DozeWallpaperState(
+            IWallpaperManager wallpaperManagerService,
+            BiometricUnlockController biometricUnlockController,
+            DozeParameters parameters) {
         mWallpaperManagerService = wallpaperManagerService;
         mBiometricUnlockController = biometricUnlockController;
         mDozeParameters = parameters;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 1d2de60..e66a9fa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -60,7 +60,6 @@
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
 import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
 import com.android.systemui.util.wakelock.SettableWakeLock;
 import com.android.systemui.util.wakelock.WakeLock;
 
@@ -107,8 +106,8 @@
     protected final Uri mMediaUri;
     private final Date mCurrentTime = new Date();
     private final Handler mHandler;
+    private final Handler mMediaHandler;
     private final AlarmManager.OnAlarmListener mUpdateNextAlarm = this::updateNextAlarm;
-    private final Object mMediaToken = new Object();
     private DozeParameters mDozeParameters;
     @VisibleForTesting
     protected SettableWakeLock mMediaWakeLock;
@@ -174,17 +173,13 @@
                 }
             };
 
-    public KeyguardSliceProvider() {
-        this(new Handler());
-    }
-
     public static KeyguardSliceProvider getAttachedInstance() {
         return KeyguardSliceProvider.sInstance;
     }
 
-    @VisibleForTesting
-    KeyguardSliceProvider(Handler handler) {
-        mHandler = handler;
+    public KeyguardSliceProvider() {
+        mHandler = new Handler();
+        mMediaHandler = new Handler();
         mSliceUri = Uri.parse(KEYGUARD_SLICE_URI);
         mHeaderUri = Uri.parse(KEYGUARD_HEADER_URI);
         mDateUri = Uri.parse(KEYGUARD_DATE_URI);
@@ -328,7 +323,7 @@
             mContentResolver = getContext().getContentResolver();
             mNextAlarmController = new NextAlarmControllerImpl(getContext());
             mNextAlarmController.addCallback(this);
-            mZenModeController = new ZenModeControllerImpl(getContext(), mHandler);
+            mZenModeController = Dependency.get(ZenModeController.class);
             mZenModeController.addCallback(this);
             mDatePattern = getContext().getString(R.string.system_ui_aod_date_pattern);
             mPendingIntent = PendingIntent.getActivity(getContext(), 0, new Intent(), 0);
@@ -470,16 +465,18 @@
     public void onMetadataOrStateChanged(MediaMetadata metadata, @PlaybackState.State int state) {
         synchronized (this) {
             boolean nextVisible = NotificationMediaManager.isPlayingState(state);
-            mHandler.removeCallbacksAndMessages(mMediaToken);
+            mMediaHandler.removeCallbacksAndMessages(null);
             if (mMediaIsVisible && !nextVisible && mStatusBarState != StatusBarState.SHADE) {
                 // We need to delay this event for a few millis when stopping to avoid jank in the
                 // animation. The media app might not send its update when buffering, and the slice
                 // would end up without a header for 0.5 second.
                 mMediaWakeLock.setAcquired(true);
-                mHandler.postDelayed(() -> {
-                    updateMediaStateLocked(metadata, state);
-                    mMediaWakeLock.setAcquired(false);
-                }, mMediaToken, 2000);
+                mMediaHandler.postDelayed(() -> {
+                    synchronized (this) {
+                        updateMediaStateLocked(metadata, state);
+                        mMediaWakeLock.setAcquired(false);
+                    }
+                }, 2000);
             } else {
                 mMediaWakeLock.setAcquired(false);
                 updateMediaStateLocked(metadata, state);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index e0270de..5e38f2e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -68,6 +68,7 @@
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.IKeyguardDrawnCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
@@ -685,16 +686,22 @@
             Context context,
             FalsingManager falsingManager,
             LockPatternUtils lockPatternUtils) {
+        this(context, falsingManager, lockPatternUtils, SystemUIFactory.getInstance());
+    }
+
+    @VisibleForTesting
+    KeyguardViewMediator(
+            Context context,
+            FalsingManager falsingManager,
+            LockPatternUtils lockPatternUtils,
+            SystemUIFactory systemUIFactory) {
         super(context);
-
         mFalsingManager = falsingManager;
-
         mLockPatternUtils = lockPatternUtils;
-        mStatusBarKeyguardViewManager =
-                SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(
-                        mContext,
-                        mViewMediatorCallback,
-                        mLockPatternUtils);
+        mStatusBarKeyguardViewManager = systemUIFactory.createStatusBarKeyguardViewManager(
+                mContext,
+                mViewMediatorCallback,
+                mLockPatternUtils);
     }
 
     public void userActivity() {
@@ -826,6 +833,9 @@
             mDeviceInteractive = false;
             mGoingToSleep = true;
 
+            // Reset keyguard going away state so we can start listening for biometric auth
+            setKeyguardGoingAway(false);
+
             // Lock immediately based on setting if secure (user has a pin/pattern/password).
             // This also "locks" the device when not secure to provide easy access to the
             // camera while preventing unwanted input.
@@ -1572,12 +1582,14 @@
                     handleNotifyFinishedGoingToSleep();
                     break;
                 case NOTIFY_SCREEN_TURNING_ON:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNING_ON");
+                    Trace.beginSection(
+                            "KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNING_ON");
                     handleNotifyScreenTurningOn((IKeyguardDrawnCallback) msg.obj);
                     Trace.endSection();
                     break;
                 case NOTIFY_SCREEN_TURNED_ON:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNED_ON");
+                    Trace.beginSection(
+                            "KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNED_ON");
                     handleNotifyScreenTurnedOn();
                     Trace.endSection();
                     break;
@@ -1585,7 +1597,8 @@
                     handleNotifyScreenTurnedOff();
                     break;
                 case NOTIFY_STARTED_WAKING_UP:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage NOTIFY_STARTED_WAKING_UP");
+                    Trace.beginSection(
+                            "KeyguardViewMediator#handleMessage NOTIFY_STARTED_WAKING_UP");
                     handleNotifyStartedWakingUp();
                     Trace.endSection();
                     break;
@@ -1614,14 +1627,16 @@
                     handleDismiss(message.getCallback(), message.getMessage());
                     break;
                 case START_KEYGUARD_EXIT_ANIM:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
+                    Trace.beginSection(
+                            "KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
                     StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj;
                     handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration);
                     mFalsingManager.onSucccessfulUnlock();
                     Trace.endSection();
                     break;
                 case KEYGUARD_DONE_PENDING_TIMEOUT:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage KEYGUARD_DONE_PENDING_TIMEOUT");
+                    Trace.beginSection("KeyguardViewMediator#handleMessage"
+                            + " KEYGUARD_DONE_PENDING_TIMEOUT");
                     Log.w(TAG, "Timeout while waiting for activity drawn!");
                     Trace.endSection();
                     break;
@@ -1799,8 +1814,7 @@
             mHideAnimationRun = false;
             adjustStatusBarLocked();
             userActivity();
-            mUpdateMonitor.setKeyguardGoingAway(false /* away */);
-            mStatusBarWindowController.setKeyguardGoingAway(false /* goingAway */);
+            setKeyguardGoingAway(false);
             mShowKeyguardWakeLock.release();
         }
         mKeyguardDisplayManager.show();
@@ -1832,8 +1846,7 @@
                         .KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS;
             }
 
-            mUpdateMonitor.setKeyguardGoingAway(true /* goingAway */);
-            mStatusBarWindowController.setKeyguardGoingAway(true /* goingAway */);
+            setKeyguardGoingAway(true);
 
             // Don't actually hide the Keyguard at the moment, wait for window
             // manager until it tells us it's safe to do so with
@@ -2068,6 +2081,11 @@
         mHandler.removeMessages(KEYGUARD_DONE_PENDING_TIMEOUT);
     }
 
+    private void setKeyguardGoingAway(boolean goingAway) {
+        mUpdateMonitor.setKeyguardGoingAway(goingAway);
+        mStatusBarWindowController.setKeyguardGoingAway(goingAway);
+    }
+
     @Override
     public void onBootCompleted() {
         mUpdateMonitor.dispatchBootCompleted();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index a9fe54b..4d061e1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -49,6 +49,12 @@
     private static final String TAG = "WorkLockActivity";
 
     /**
+     * Add additional extra {@link com.android.settings.password.ConfirmDeviceCredentialActivity} to
+     * enable device policy management enforcement from systemui.
+     */
+    public static final String EXTRA_FROM_WORK_LOCK_ACTIVITY = "from_work_lock_activity";
+
+    /**
      * Contains a {@link TaskDescription} for the activity being covered.
      */
     static final String EXTRA_TASK_DESCRIPTION =
@@ -151,6 +157,7 @@
 
         if (target != null) {
             credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender());
+            credential.putExtra(EXTRA_FROM_WORK_LOCK_ACTIVITY, true);
         }
 
         startActivityForResult(credential, REQUEST_CODE_CONFIRM_CREDENTIALS);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index 8224365..3f15966 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -107,7 +107,7 @@
                             | LayoutParams.FLAG_NOT_FOCUSABLE,
                     PixelFormat.TRANSLUCENT);
             lp.setTitle("pip-dismiss-overlay");
-            lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+            lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
             lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
             mWindowManager.addView(mDismissView, lp);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index ae83567..2e24403 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -28,10 +28,12 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.provider.Settings;
 import android.service.quicksettings.Tile;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 
 import com.android.internal.logging.MetricsLogger;
@@ -49,6 +51,8 @@
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.settings.BrightnessController;
 import com.android.systemui.settings.ToggleSliderView;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.phone.NPVPluginManager;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController.BrightnessMirrorListener;
 import com.android.systemui.tuner.TunerService;
@@ -98,6 +102,10 @@
     private BrightnessMirrorController mBrightnessMirrorController;
     private View mDivider;
 
+    private FrameLayout mPluginFrame;
+    private final PluginManager mPluginManager;
+    private NPVPluginManager mNPVPluginManager;
+
     public QSPanel(Context context) {
         this(context, null);
     }
@@ -106,9 +114,13 @@
         this(context, attrs, null);
     }
 
+    public QSPanel(Context context, AttributeSet attrs, DumpController dumpController) {
+        this(context, attrs, dumpController, null);
+    }
+
     @Inject
     public QSPanel(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
-            DumpController dumpController) {
+            DumpController dumpController, PluginManager pluginManager) {
         super(context, attrs);
         mContext = context;
 
@@ -136,6 +148,15 @@
         mBrightnessController = new BrightnessController(getContext(),
                 findViewById(R.id.brightness_slider));
         mDumpController = dumpController;
+        mPluginManager = pluginManager;
+        if (mPluginManager != null && Settings.System.getInt(
+                mContext.getContentResolver(), "npv_plugin_flag", 0) == 2) {
+            mPluginFrame = (FrameLayout) LayoutInflater.from(mContext).inflate(
+                    R.layout.status_bar_expanded_plugin_frame, this, false);
+            addView(mPluginFrame);
+            mNPVPluginManager = new NPVPluginManager(mPluginFrame, mPluginManager);
+        }
+
     }
 
     protected void addDivider() {
@@ -377,6 +398,7 @@
         if (mListening) {
             refreshAllTiles();
         }
+        if (mNPVPluginManager != null) mNPVPluginManager.setListening(listening);
     }
 
     public void setListening(boolean listening, boolean expanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 466c808..411980b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -39,6 +39,7 @@
 import android.util.Log;
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
+import android.widget.Switch;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
@@ -82,6 +83,11 @@
         mTile = new Tile();
         updateDefaultTileAndIcon();
         mServiceManager = host.getTileServices().getTileWrapper(this);
+        if (mServiceManager.isBooleanTile()) {
+            // Replace states with BooleanState
+            resetStates();
+        }
+
         mService = mServiceManager.getTileService();
         mServiceManager.setTileChangeListener(this);
         mUser = ActivityManager.getCurrentUser();
@@ -246,8 +252,10 @@
 
     @Override
     public State newTileState() {
-        State state = new State();
-        return state;
+        if (mServiceManager != null && mServiceManager.isBooleanTile()) {
+            return new BooleanState();
+        }
+        return new State();
     }
 
     @Override
@@ -336,6 +344,12 @@
         } else {
             state.contentDescription = state.label;
         }
+
+        if (state instanceof BooleanState) {
+            state.expandedAccessibilityClassName = Switch.class.getName();
+            ((BooleanState) state).value = (state.state == Tile.STATE_ACTIVE);
+        }
+
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index effea6a..f59e0c2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -131,6 +131,24 @@
     }
 
     /**
+     * Determines whether the associated TileService is a Boolean Tile.
+     *
+     * @return true if {@link TileService#META_DATA_BOOLEAN_TILE} is set to {@code true} for this
+     *         tile
+     * @see TileService#META_DATA_BOOLEAN_TILE
+     */
+    public boolean isBooleanTile() {
+        try {
+            ServiceInfo info = mPackageManagerAdapter.getServiceInfo(mIntent.getComponent(),
+                    PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_META_DATA);
+            return info.metaData != null
+                    && info.metaData.getBoolean(TileService.META_DATA_BOOLEAN_TILE, false);
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+    }
+
+    /**
      * Binds just long enough to send any queued messages, then unbinds.
      */
     public void flushMessagesAndUnbind() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 2a7e55f..0b4e648 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -123,6 +123,10 @@
         return mStateManager.isActiveTile();
     }
 
+    public boolean isBooleanTile() {
+        return mStateManager.isBooleanTile();
+    }
+
     public void setShowingDialog(boolean dialog) {
         mShowingDialog = dialog;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index daaee4c..1c8e451 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -16,6 +16,7 @@
 
 import android.content.Context;
 import android.os.Build;
+import android.provider.Settings;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 
@@ -32,6 +33,7 @@
 import com.android.systemui.qs.tiles.CastTile;
 import com.android.systemui.qs.tiles.CellularTile;
 import com.android.systemui.qs.tiles.ColorInversionTile;
+import com.android.systemui.qs.tiles.ControlsTile;
 import com.android.systemui.qs.tiles.DataSaverTile;
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.qs.tiles.FlashlightTile;
@@ -58,6 +60,7 @@
 
     private final Provider<WifiTile> mWifiTileProvider;
     private final Provider<BluetoothTile> mBluetoothTileProvider;
+    private final Provider<ControlsTile> mControlsTileProvider;
     private final Provider<CellularTile> mCellularTileProvider;
     private final Provider<DndTile> mDndTileProvider;
     private final Provider<ColorInversionTile> mColorInversionTileProvider;
@@ -81,6 +84,7 @@
     @Inject
     public QSFactoryImpl(Provider<WifiTile> wifiTileProvider,
             Provider<BluetoothTile> bluetoothTileProvider,
+            Provider<ControlsTile> controlsTileProvider,
             Provider<CellularTile> cellularTileProvider,
             Provider<DndTile> dndTileProvider,
             Provider<ColorInversionTile> colorInversionTileProvider,
@@ -100,6 +104,7 @@
             Provider<UiModeNightTile> uiModeNightTileProvider) {
         mWifiTileProvider = wifiTileProvider;
         mBluetoothTileProvider = bluetoothTileProvider;
+        mControlsTileProvider = controlsTileProvider;
         mCellularTileProvider = cellularTileProvider;
         mDndTileProvider = dndTileProvider;
         mColorInversionTileProvider = colorInversionTileProvider;
@@ -138,6 +143,11 @@
                 return mWifiTileProvider.get();
             case "bt":
                 return mBluetoothTileProvider.get();
+            case "controls":
+                if (Settings.System.getInt(mHost.getContext().getContentResolver(),
+                        "qs_controls_tile_enabled", 0) == 1) {
+                    return mControlsTileProvider.get();
+                } else return null;
             case "cell":
                 return mCellularTileProvider.get();
             case "dnd":
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 681de37..e0f26cd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -139,6 +139,11 @@
         mQSSettingsPanelOption = QSSettingsControllerKt.getQSSettingsPanelOption();
     }
 
+    protected final void resetStates() {
+        mState = newTileState();
+        mTmpState = newTileState();
+    }
+
     @NonNull
     @Override
     public Lifecycle getLifecycle() {
@@ -629,6 +634,11 @@
         }
     }
 
+    /**
+     * Dumps the state of this tile along with its name.
+     *
+     * This may be used for CTS testing of tiles.
+     */
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println(this.getClass().getSimpleName() + ":");
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java
new file mode 100644
index 0000000..0a59618
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.HomeControlsPlugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.qs.DetailAdapter;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.shared.plugins.PluginManager;
+
+import javax.inject.Inject;
+
+
+/**
+ * Temporary control test for prototyping
+ */
+public class ControlsTile extends QSTileImpl<BooleanState> {
+    private ControlsDetailAdapter mDetailAdapter;
+    private final ActivityStarter mActivityStarter;
+    private PluginManager mPluginManager;
+    private HomeControlsPlugin mPlugin;
+    private Intent mHomeAppIntent;
+
+    @Inject
+    public ControlsTile(QSHost host,
+            ActivityStarter activityStarter,
+            PluginManager pluginManager) {
+        super(host);
+        mActivityStarter = activityStarter;
+        mPluginManager = pluginManager;
+        mDetailAdapter = (ControlsDetailAdapter) createDetailAdapter();
+
+        mHomeAppIntent = new Intent(Intent.ACTION_VIEW);
+        mHomeAppIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mHomeAppIntent.setComponent(new ComponentName("com.google.android.apps.chromecast.app",
+                "com.google.android.apps.chromecast.app.DiscoveryActivity"));
+    }
+
+    @Override
+    public DetailAdapter getDetailAdapter() {
+        return mDetailAdapter;
+    }
+
+    @Override
+    public BooleanState newTileState() {
+        return new BooleanState();
+    }
+
+    @Override
+    public void handleSetListening(boolean listening) {
+
+    }
+
+    @Override
+    public void setDetailListening(boolean listening) {
+        if (mPlugin == null) return;
+
+        mPlugin.setVisible(listening);
+    }
+
+    @Override
+    protected void handleClick() {
+        showDetail(true);
+    }
+
+    @Override
+    public Intent getLongClickIntent() {
+        return mHomeAppIntent;
+    }
+
+    @Override
+    protected void handleSecondaryClick() {
+        showDetail(true);
+    }
+
+    @Override
+    public CharSequence getTileLabel() {
+        return "Controls";
+    }
+
+    @Override
+    protected void handleUpdateState(BooleanState state, Object arg) {
+        state.icon = ResourceIcon.get(R.drawable.ic_lightbulb_outline_gm2_24px);
+        state.label = "Controls";
+    }
+
+    @Override
+    public boolean supportsDetailView() {
+        return getDetailAdapter() != null && mQSSettingsPanelOption == QSSettingsPanel.OPEN_CLICK;
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return -1;
+    }
+
+    @Override
+    protected String composeChangeAnnouncement() {
+        if (mState.value) {
+            return "On";
+        } else {
+            return "Off";
+        }
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    protected DetailAdapter createDetailAdapter() {
+        mDetailAdapter = new ControlsDetailAdapter();
+        return mDetailAdapter;
+    }
+
+    private class ControlsDetailAdapter implements DetailAdapter {
+        private View mDetailView;
+        protected LinearLayout mHomeControlsLayout;
+
+        public CharSequence getTitle() {
+            return "Controls";
+        }
+
+        public Boolean getToggleState() {
+            return null;
+        }
+
+        public boolean getToggleEnabled() {
+            return false;
+        }
+
+        public View createDetailView(Context context, View convertView, final ViewGroup parent) {
+            mHomeControlsLayout = (LinearLayout) LayoutInflater.from(context).inflate(
+                R.layout.home_controls, parent, false);
+            mHomeControlsLayout.setVisibility(View.VISIBLE);
+            mPluginManager.addPluginListener(
+                    new PluginListener<HomeControlsPlugin>() {
+                        @Override
+                        public void onPluginConnected(HomeControlsPlugin plugin,
+                                                      Context pluginContext) {
+                            mPlugin = plugin;
+                            mPlugin.sendParentGroup(mHomeControlsLayout);
+                            mPlugin.setVisible(true);
+                        }
+
+                        @Override
+                        public void onPluginDisconnected(HomeControlsPlugin plugin) {
+
+                        }
+                    }, HomeControlsPlugin.class, false);
+            return mHomeControlsLayout;
+        }
+
+        public Intent getSettingsIntent() {
+            return mHomeAppIntent;
+        }
+
+        public void setToggleState(boolean state) {
+
+        }
+
+        public int getMetricsCategory() {
+            return -1;
+        }
+
+        public boolean hasHeader() {
+            return false;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index c1ce163..aa64449 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -497,7 +497,7 @@
                 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                 flags,
                 PixelFormat.TRANSLUCENT);
-        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+        lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         lp.setTitle("RecentsOnboarding");
         lp.gravity = gravity;
         return lp;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 0f277ca..2d1c087 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -128,7 +128,7 @@
                         | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                 PixelFormat.TRANSLUCENT);
         lp.token = new Binder();
-        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+        lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         lp.setTitle("ScreenPinningConfirmation");
         lp.gravity = Gravity.FILL;
         return lp;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index 33bcefb..e24a362 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -65,7 +65,7 @@
             Log.v(TAG, "showNotification");
         }
         addAlertEntry(entry);
-        updateNotification(entry.key, true /* alert */);
+        updateNotification(entry.getKey(), true /* alert */);
         entry.setInterruption();
     }
 
@@ -182,7 +182,7 @@
     protected final void addAlertEntry(@NonNull NotificationEntry entry) {
         AlertEntry alertEntry = createAlertEntry();
         alertEntry.setEntry(entry);
-        mAlertEntries.put(entry.key, alertEntry);
+        mAlertEntries.put(entry.getKey(), alertEntry);
         onAlertEntryAdded(alertEntry);
         entry.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
     }
@@ -251,7 +251,7 @@
 
     @Override
     public boolean shouldExtendLifetime(NotificationEntry entry) {
-        return !canRemoveImmediately(entry.key);
+        return !canRemoveImmediately(entry.getKey());
     }
 
     @Override
@@ -260,7 +260,7 @@
             mExtendedLifetimeAlertEntries.add(entry);
             // We need to make sure that entries are stopping to alert eventually, let's remove
             // this as soon as possible.
-            AlertEntry alertEntry = mAlertEntries.get(entry.key);
+            AlertEntry alertEntry = mAlertEntries.get(entry.getKey());
             alertEntry.removeAsSoonAsPossible();
         } else {
             mExtendedLifetimeAlertEntries.remove(entry);
@@ -276,7 +276,7 @@
         @Nullable protected Runnable mRemoveAlertRunnable;
 
         public void setEntry(@NonNull final NotificationEntry entry) {
-            setEntry(entry, () -> removeAlertEntry(entry.key));
+            setEntry(entry, () -> removeAlertEntry(entry.getKey()));
         }
 
         public void setEntry(@NonNull final NotificationEntry entry,
@@ -332,7 +332,7 @@
         public int compareTo(@NonNull AlertEntry alertEntry) {
             return (mPostTime < alertEntry.mPostTime)
                     ? 1 : ((mPostTime == alertEntry.mPostTime)
-                            ? mEntry.key.compareTo(alertEntry.mEntry.key) : -1);
+                            ? mEntry.getKey().compareTo(alertEntry.mEntry.getKey()) : -1);
         }
 
         public void reset() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
new file mode 100644
index 0000000..0679595
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -0,0 +1,83 @@
+/*
+ * 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.statusbar;
+
+import static com.android.systemui.Dependency.BG_HANDLER_NAME;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.provider.DeviceConfig;
+import android.util.ArrayMap;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+/**
+ * Class to manage simple DeviceConfig-based feature flags.
+ *
+ * To enable or disable a flag, run:
+ *
+ * {@code
+ *  $ adb shell device_config put systemui <key> <true|false>
+*  }
+ *
+ * You will probably need to restart systemui for the changes to be picked up:
+ *
+ * {@code
+ *  $ adb shell am crash com.android.systemui
+ * }
+ */
+@Singleton
+public class FeatureFlags {
+    private final Map<String, Boolean> mCachedDeviceConfigFlags = new ArrayMap<>();
+
+    @Inject
+    public FeatureFlags(
+            @Named(BG_HANDLER_NAME) Handler bgHandler) {
+        DeviceConfig.addOnPropertiesChangedListener(
+                "systemui",
+                new HandlerExecutor(bgHandler),
+                this::onPropertiesChanged);
+    }
+
+    public boolean isNewNotifPipelineEnabled() {
+        return getDeviceConfigFlag("notification.newpipeline.enabled", false);
+    }
+
+    private void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
+        synchronized (mCachedDeviceConfigFlags) {
+            for (String key : properties.getKeyset()) {
+                mCachedDeviceConfigFlags.remove(key);
+            }
+        }
+    }
+
+    private boolean getDeviceConfigFlag(String key, boolean defaultValue) {
+        synchronized (mCachedDeviceConfigFlags) {
+            Boolean flag = mCachedDeviceConfigFlags.get(key);
+            if (flag == null) {
+                flag = DeviceConfig.getBoolean("systemui", key, defaultValue);
+                mCachedDeviceConfigFlags.put(key, flag);
+            }
+            return flag;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index e09e9cd..5144a95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -233,11 +233,13 @@
     }
 
     /** @return {@link NavigationBarFragment} on the default display. */
+    @Nullable
     public NavigationBarFragment getDefaultNavigationBarFragment() {
         return mNavigationBars.get(DEFAULT_DISPLAY);
     }
 
     /** @return {@link AssistHandleViewController} (only on the default display). */
+    @Nullable
     public AssistHandleViewController getAssistHandlerViewController() {
         NavigationBarFragment navBar = getDefaultNavigationBarFragment();
         return navBar == null ? null : navBar.getAssistHandlerViewController();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 6ffea79..7adf7af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -323,7 +323,7 @@
             exceedsPriorityThreshold = entry.getBucket() != BUCKET_SILENT;
         } else {
             exceedsPriorityThreshold =
-                    !getEntryManager().getNotificationData().isAmbient(entry.key);
+                    !getEntryManager().getNotificationData().isAmbient(entry.getKey());
         }
         return mShowLockscreenNotifications && exceedsPriorityThreshold;
     }
@@ -445,15 +445,15 @@
 
     /** @return true if the entry needs redaction when on the lockscreen. */
     public boolean needsRedaction(NotificationEntry ent) {
-        int userId = ent.notification.getUserId();
+        int userId = ent.getSbn().getUserId();
 
         boolean currentUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(mCurrentUserId);
         boolean notiUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(userId);
         boolean redactedLockscreen = currentUserWantsRedaction || notiUserWantsRedaction;
 
         boolean notificationRequestsRedaction =
-                ent.notification.getNotification().visibility == Notification.VISIBILITY_PRIVATE;
-        boolean userForcesRedaction = packageHasVisibilityOverride(ent.notification.getKey());
+                ent.getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE;
+        boolean userForcesRedaction = packageHasVisibilityOverride(ent.getSbn().getKey());
 
         return userForcesRedaction || notificationRequestsRedaction && redactedLockscreen;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 3616b54..0988e34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -204,7 +204,7 @@
                     NotificationEntry entry,
                     NotificationVisibility visibility,
                     boolean removedByUser) {
-                onNotificationRemoved(entry.key);
+                onNotificationRemoved(entry.getKey());
             }
         });
 
@@ -284,7 +284,7 @@
 
                 if (entry.isMediaNotification()) {
                     final MediaSession.Token token =
-                            entry.notification.getNotification().extras.getParcelable(
+                            entry.getSbn().getNotification().extras.getParcelable(
                                     Notification.EXTRA_MEDIA_SESSION);
                     if (token != null) {
                         MediaController aController = new MediaController(mContext, token);
@@ -292,7 +292,7 @@
                                 getMediaControllerPlaybackState(aController)) {
                             if (DEBUG_MEDIA) {
                                 Log.v(TAG, "DEBUG_MEDIA: found mediastyle controller matching "
-                                        + entry.notification.getKey());
+                                        + entry.getSbn().getKey());
                             }
                             mediaNotification = entry;
                             controller = aController;
@@ -321,10 +321,10 @@
 
                             for (int i = 0; i < N; i++) {
                                 final NotificationEntry entry = activeNotifications.get(i);
-                                if (entry.notification.getPackageName().equals(pkg)) {
+                                if (entry.getSbn().getPackageName().equals(pkg)) {
                                     if (DEBUG_MEDIA) {
                                         Log.v(TAG, "DEBUG_MEDIA: found controller matching "
-                                                + entry.notification.getKey());
+                                                + entry.getSbn().getKey());
                                     }
                                     controller = aController;
                                     mediaNotification = entry;
@@ -351,8 +351,8 @@
             }
 
             if (mediaNotification != null
-                    && !mediaNotification.notification.getKey().equals(mMediaNotificationKey)) {
-                mMediaNotificationKey = mediaNotification.notification.getKey();
+                    && !mediaNotification.getSbn().getKey().equals(mMediaNotificationKey)) {
+                mMediaNotificationKey = mediaNotification.getSbn().getKey();
                 if (DEBUG_MEDIA) {
                     Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key="
                             + mMediaNotificationKey);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index c9050d4..23968d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -293,7 +293,7 @@
                 mSmartReplyController.stopSending(entry);
 
                 if (removedByUser && entry != null) {
-                    onPerformRemoveNotification(entry, entry.key);
+                    onPerformRemoveNotification(entry, entry.getKey());
                 }
             }
         });
@@ -307,8 +307,8 @@
             @Override
             public void onRemoteInputSent(NotificationEntry entry) {
                 if (FORCE_REMOTE_INPUT_HISTORY
-                        && isNotificationKeptForRemoteInputHistory(entry.key)) {
-                    mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
+                        && isNotificationKeptForRemoteInputHistory(entry.getKey())) {
+                    mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
                 } else if (mEntriesKeptForRemoteInputActive.contains(entry)) {
                     // We're currently holding onto this notification, but from the apps point of
                     // view it is already canceled, so we'll need to cancel it on the apps behalf
@@ -316,18 +316,18 @@
                     // bit.
                     mMainHandler.postDelayed(() -> {
                         if (mEntriesKeptForRemoteInputActive.remove(entry)) {
-                            mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
+                            mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
                         }
                     }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY);
                 }
                 try {
-                    mBarService.onNotificationDirectReplied(entry.notification.getKey());
+                    mBarService.onNotificationDirectReplied(entry.getSbn().getKey());
                     if (entry.editedSuggestionInfo != null) {
                         boolean modifiedBeforeSending =
                                 !TextUtils.equals(entry.remoteInputText,
                                         entry.editedSuggestionInfo.originalText);
                         mBarService.onNotificationSmartReplySent(
-                                entry.notification.getKey(),
+                                entry.getSbn().getKey(),
                                 entry.editedSuggestionInfo.index,
                                 entry.editedSuggestionInfo.originalText,
                                 NotificationLogger
@@ -487,7 +487,7 @@
             NotificationEntry entry = mEntriesKeptForRemoteInputActive.valueAt(i);
             mRemoteInputController.removeRemoteInput(entry, null);
             if (mNotificationLifetimeFinishedCallback != null) {
-                mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
+                mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
             }
         }
         mEntriesKeptForRemoteInputActive.clear();
@@ -501,14 +501,15 @@
         if (!FORCE_REMOTE_INPUT_HISTORY) {
             return false;
         }
-        return (mRemoteInputController.isSpinning(entry.key) || entry.hasJustSentRemoteInput());
+        return (mRemoteInputController.isSpinning(entry.getKey())
+                || entry.hasJustSentRemoteInput());
     }
 
     public boolean shouldKeepForSmartReplyHistory(NotificationEntry entry) {
         if (!FORCE_REMOTE_INPUT_HISTORY) {
             return false;
         }
-        return mSmartReplyController.isSendingSmartReply(entry.key);
+        return mSmartReplyController.isSendingSmartReply(entry.getKey());
     }
 
     public void checkRemoteInputOutside(MotionEvent event) {
@@ -529,7 +530,7 @@
     @VisibleForTesting
     StatusBarNotification rebuildNotificationWithRemoteInput(NotificationEntry entry,
             CharSequence remoteInputText, boolean showSpinner) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
 
         Notification.Builder b = Notification.Builder
                 .recoverBuilder(mContext, sbn.getNotification().clone());
@@ -637,12 +638,12 @@
 
                 if (Log.isLoggable(TAG, Log.DEBUG)) {
                     Log.d(TAG, "Keeping notification around after sending remote input "
-                            + entry.key);
+                            + entry.getKey());
                 }
 
-                mKeysKeptForRemoteInputHistory.add(entry.key);
+                mKeysKeptForRemoteInputHistory.add(entry.getKey());
             } else {
-                mKeysKeptForRemoteInputHistory.remove(entry.key);
+                mKeysKeptForRemoteInputHistory.remove(entry.getKey());
             }
         }
     }
@@ -675,12 +676,12 @@
 
                 if (Log.isLoggable(TAG, Log.DEBUG)) {
                     Log.d(TAG, "Keeping notification around after sending smart reply "
-                            + entry.key);
+                            + entry.getKey());
                 }
 
-                mKeysKeptForRemoteInputHistory.add(entry.key);
+                mKeysKeptForRemoteInputHistory.add(entry.getKey());
             } else {
-                mKeysKeptForRemoteInputHistory.remove(entry.key);
+                mKeysKeptForRemoteInputHistory.remove(entry.getKey());
                 mSmartReplyController.stopSending(entry);
             }
         }
@@ -701,7 +702,7 @@
             if (shouldExtend) {
                 if (Log.isLoggable(TAG, Log.DEBUG)) {
                     Log.d(TAG, "Keeping notification around while remote input active "
-                            + entry.key);
+                            + entry.getKey());
                 }
                 mEntriesKeptForRemoteInputActive.add(entry);
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
index 266fe8d..564d8bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
@@ -54,7 +54,7 @@
     public static NotificationUiAdjustment extractFromNotificationEntry(
             NotificationEntry entry) {
         return new NotificationUiAdjustment(
-                entry.key, entry.getSmartActions(), entry.getSmartReplies());
+                entry.getKey(), entry.getSmartActions(), entry.getSmartReplies());
     }
 
     public static boolean needReinflate(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 50d9bae..c2bb5b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -147,13 +147,13 @@
         for (int i = 0; i < N; i++) {
             NotificationEntry ent = activeNotifications.get(i);
             if (ent.isRowDismissed() || ent.isRowRemoved()
-                    || mBubbleController.isBubbleNotificationSuppressedFromShade(ent.key)) {
+                    || mBubbleController.isBubbleNotificationSuppressedFromShade(ent.getKey())) {
                 // we don't want to update removed notifications because they could
                 // temporarily become children if they were isolated before.
                 continue;
             }
 
-            int userId = ent.notification.getUserId();
+            int userId = ent.getSbn().getUserId();
 
             // Display public version of the notification if we need to redact.
             // TODO: This area uses a lot of calls into NotificationLockscreenUserManager.
@@ -174,8 +174,8 @@
                     currentUserId);
             ent.setSensitive(sensitive, deviceSensitive);
             ent.getRow().setNeedsRedaction(needsRedaction);
-            if (mGroupManager.isChildInGroupWithSummary(ent.notification)) {
-                NotificationEntry summary = mGroupManager.getGroupSummary(ent.notification);
+            if (mGroupManager.isChildInGroupWithSummary(ent.getSbn())) {
+                NotificationEntry summary = mGroupManager.getGroupSummary(ent.getSbn());
                 List<ExpandableNotificationRow> orderedChildren =
                         mTmpChildOrderMap.get(summary.getRow());
                 if (orderedChildren == null) {
@@ -382,7 +382,7 @@
             ExpandableNotificationRow row = stack.pop();
             NotificationEntry entry = row.getEntry();
             boolean isChildNotification =
-                    mGroupManager.isChildInGroupWithSummary(entry.notification);
+                    mGroupManager.isChildInGroupWithSummary(entry.getSbn());
 
             row.setOnKeyguard(onKeyguard);
 
@@ -394,15 +394,15 @@
                         && !row.isLowPriority()));
             }
 
-            int userId = entry.notification.getUserId();
+            int userId = entry.getSbn().getUserId();
             boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
-                    entry.notification) && !entry.isRowRemoved();
+                    entry.getSbn()) && !entry.isRowRemoved();
             boolean showOnKeyguard = mLockscreenUserManager.shouldShowOnKeyguard(entry);
             if (!showOnKeyguard) {
                 // min priority notifications should show if their summary is showing
-                if (mGroupManager.isChildInGroupWithSummary(entry.notification)) {
+                if (mGroupManager.isChildInGroupWithSummary(entry.getSbn())) {
                     NotificationEntry summary = mGroupManager.getLogicalGroupSummary(
-                            entry.notification);
+                            entry.getSbn());
                     if (summary != null && mLockscreenUserManager.shouldShowOnKeyguard(summary)) {
                         showOnKeyguard = true;
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index 736b9eb..7bdb21d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -58,9 +58,9 @@
     public void smartReplySent(NotificationEntry entry, int replyIndex, CharSequence reply,
             int notificationLocation, boolean modifiedBeforeSending) {
         mCallback.onSmartReplySent(entry, reply);
-        mSendingKeys.add(entry.key);
+        mSendingKeys.add(entry.getKey());
         try {
-            mBarService.onNotificationSmartReplySent(entry.notification.getKey(), replyIndex, reply,
+            mBarService.onNotificationSmartReplySent(entry.getSbn().getKey(), replyIndex, reply,
                     notificationLocation, modifiedBeforeSending);
         } catch (RemoteException e) {
             // Nothing to do, system going down
@@ -74,14 +74,14 @@
             NotificationEntry entry, int actionIndex, Notification.Action action,
             boolean generatedByAssistant) {
         final int count = mEntryManager.getNotificationData().getActiveNotifications().size();
-        final int rank = mEntryManager.getNotificationData().getRank(entry.key);
+        final int rank = mEntryManager.getNotificationData().getRank(entry.getKey());
         NotificationVisibility.NotificationLocation location =
                 NotificationLogger.getNotificationLocation(entry);
         final NotificationVisibility nv = NotificationVisibility.obtain(
-                entry.key, rank, count, true, location);
+                entry.getKey(), rank, count, true, location);
         try {
             mBarService.onNotificationActionClick(
-                    entry.key, actionIndex, action, nv, generatedByAssistant);
+                    entry.getKey(), actionIndex, action, nv, generatedByAssistant);
         } catch (RemoteException e) {
             // Nothing to do, system going down
         }
@@ -101,7 +101,7 @@
     public void smartSuggestionsAdded(final NotificationEntry entry, int replyCount,
             int actionCount, boolean generatedByAssistant, boolean editBeforeSending) {
         try {
-            mBarService.onNotificationSmartSuggestionsAdded(entry.notification.getKey(), replyCount,
+            mBarService.onNotificationSmartSuggestionsAdded(entry.getSbn().getKey(), replyCount,
                     actionCount, generatedByAssistant, editBeforeSending);
         } catch (RemoteException e) {
             // Nothing to do, system going down
@@ -110,7 +110,7 @@
 
     public void stopSending(final NotificationEntry entry) {
         if (entry != null) {
-            mSendingKeys.remove(entry.notification.getKey());
+            mSendingKeys.remove(entry.getSbn().getKey());
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NewNotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NewNotifPipeline.java
new file mode 100644
index 0000000..31921a4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NewNotifPipeline.java
@@ -0,0 +1,49 @@
+/*
+ * 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.statusbar.notification;
+
+import android.util.Log;
+
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Initialization code for the new notification pipeline.
+ */
+@Singleton
+public class NewNotifPipeline {
+    private final NotifCollection mNotifCollection;
+
+    @Inject
+    public NewNotifPipeline(
+            NotifCollection notifCollection) {
+        mNotifCollection = notifCollection;
+    }
+
+    /** Hooks the new pipeline up to NotificationManager */
+    public void initialize(
+            NotificationListener notificationService) {
+        mNotifCollection.attach(notificationService);
+
+        Log.d(TAG, "Notif pipeline initialized");
+    }
+
+    private static final String TAG = "NewNotifPipeline";
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineInitializer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineInitializer.java
deleted file mode 100644
index df70828..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineInitializer.java
+++ /dev/null
@@ -1,68 +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.statusbar.notification;
-
-import android.service.notification.NotificationListenerService;
-import android.service.notification.StatusBarNotification;
-import android.util.Log;
-
-import com.android.systemui.statusbar.NotificationListener;
-
-import javax.inject.Inject;
-
-/**
- * Initialization code for the new notification pipeline.
- */
-public class NotifPipelineInitializer {
-
-    @Inject
-    public NotifPipelineInitializer() {
-    }
-
-    public void initialize(
-            NotificationListener notificationService) {
-
-        // TODO Put real code here
-        notificationService.setDownstreamListener(new NotificationListener.NotifServiceListener() {
-            @Override
-            public void onNotificationPosted(StatusBarNotification sbn,
-                    NotificationListenerService.RankingMap rankingMap) {
-                Log.d(TAG, "onNotificationPosted " + sbn.getKey());
-            }
-
-            @Override
-            public void onNotificationRemoved(StatusBarNotification sbn,
-                    NotificationListenerService.RankingMap rankingMap) {
-                Log.d(TAG, "onNotificationRemoved " + sbn.getKey());
-            }
-
-            @Override
-            public void onNotificationRemoved(StatusBarNotification sbn,
-                    NotificationListenerService.RankingMap rankingMap, int reason) {
-                Log.d(TAG, "onNotificationRemoved " + sbn.getKey());
-            }
-
-            @Override
-            public void onNotificationRankingUpdate(
-                    NotificationListenerService.RankingMap rankingMap) {
-                Log.d(TAG, "onNotificationRankingUpdate");
-            }
-        });
-    }
-
-    private static final String TAG = "NotifInitializer";
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
index d71d407..005f01d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
@@ -80,7 +80,7 @@
                     NotificationEntry entry,
                     NotificationVisibility visibility,
                     boolean removedByUser) {
-                stopAlerting(entry.key);
+                stopAlerting(entry.getKey());
             }
         });
     }
@@ -104,7 +104,7 @@
                 mHeadsUpManager.showNotification(entry);
                 if (!mShadeController.get().isDozing()) {
                     // Mark as seen immediately
-                    setNotificationShown(entry.notification);
+                    setNotificationShown(entry.getSbn());
                 }
             } else {
                 entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP);
@@ -113,16 +113,16 @@
     }
 
     private void updateAlertState(NotificationEntry entry) {
-        boolean alertAgain = alertAgain(entry, entry.notification.getNotification());
+        boolean alertAgain = alertAgain(entry, entry.getSbn().getNotification());
         boolean shouldAlert;
         shouldAlert = mNotificationInterruptionStateProvider.shouldHeadsUp(entry);
-        final boolean wasAlerting = mHeadsUpManager.isAlerting(entry.key);
+        final boolean wasAlerting = mHeadsUpManager.isAlerting(entry.getKey());
         if (wasAlerting) {
             if (shouldAlert) {
-                mHeadsUpManager.updateNotification(entry.key, alertAgain);
-            } else if (!mHeadsUpManager.isEntryAutoHeadsUpped(entry.key)) {
+                mHeadsUpManager.updateNotification(entry.getKey(), alertAgain);
+            } else if (!mHeadsUpManager.isEntryAutoHeadsUpped(entry.getKey())) {
                 // We don't want this to be interrupting anymore, let's remove it
-                mHeadsUpManager.removeNotification(entry.key, false /* removeImmediately */);
+                mHeadsUpManager.removeNotification(entry.getKey(), false /* removeImmediately */);
             }
         } else if (shouldAlert && alertAgain) {
             // This notification was updated to be alerting, show it!
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 01c79b3..f565868 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -110,7 +110,7 @@
             pw.println("null");
         } else {
             for (NotificationEntry entry : mPendingNotifications.values()) {
-                pw.println(entry.notification);
+                pw.println(entry.getSbn());
             }
         }
         pw.println("  Lifetime-extended notifications:");
@@ -119,7 +119,7 @@
         } else {
             for (Map.Entry<NotificationEntry, NotificationLifetimeExtender> entry
                     : mRetainedNotifications.entrySet()) {
-                pw.println("    " + entry.getKey().notification + " retained by "
+                pw.println("    " + entry.getKey().getSbn() + " retained by "
                         + entry.getValue().getClass().getName());
             }
         }
@@ -212,13 +212,13 @@
             NotificationEntry entry = mPendingNotifications.get(key);
             entry.abortTask();
             mPendingNotifications.remove(key);
-            mNotifLog.log(NotifEvent.INFLATION_ABORTED, entry.sbn(), null,
+            mNotifLog.log(NotifEvent.INFLATION_ABORTED, entry.getSbn(), null,
                     "PendingNotification aborted. " + reason);
         }
         NotificationEntry addedEntry = mNotificationData.get(key);
         if (addedEntry != null) {
             addedEntry.abortTask();
-            mNotifLog.log(NotifEvent.INFLATION_ABORTED, addedEntry.sbn(),
+            mNotifLog.log(NotifEvent.INFLATION_ABORTED, addedEntry.getSbn(),
                     null, reason);
         }
     }
@@ -242,11 +242,11 @@
     @Override
     public void onAsyncInflationFinished(NotificationEntry entry,
             @InflationFlag int inflatedFlags) {
-        mPendingNotifications.remove(entry.key);
+        mPendingNotifications.remove(entry.getKey());
         // If there was an async task started after the removal, we don't want to add it back to
         // the list, otherwise we might get leaks.
         if (!entry.isRowRemoved()) {
-            boolean isNew = mNotificationData.get(entry.key) == null;
+            boolean isNew = mNotificationData.get(entry.getKey()) == null;
             if (isNew) {
                 for (NotificationEntryListener listener : mNotificationEntryListeners) {
                     listener.onEntryInflated(entry, inflatedFlags);
@@ -302,7 +302,7 @@
                         lifetimeExtended = true;
                         mNotifLog.log(
                                 NotifEvent.LIFETIME_EXTENDED,
-                                pendingEntry.sbn(),
+                                pendingEntry.getSbn(),
                                 "pendingEntry extendedBy=" + extender.toString());
                     }
                 }
@@ -325,7 +325,7 @@
                         lifetimeExtended = true;
                         mNotifLog.log(
                                 NotifEvent.LIFETIME_EXTENDED,
-                                entry.sbn(),
+                                entry.getSbn(),
                                 "entry extendedBy=" + extender.toString());
                         break;
                     }
@@ -350,7 +350,7 @@
                 Dependency.get(LeakDetector.class).trackGarbage(entry);
                 removedByUser |= entryDismissed;
 
-                mNotifLog.log(NotifEvent.NOTIF_REMOVED, entry.sbn(),
+                mNotifLog.log(NotifEvent.NOTIF_REMOVED, entry.getSbn(),
                         "removedByUser=" + removedByUser);
                 for (NotificationEntryListener listener : mNotificationEntryListeners) {
                     listener.onEntryRemoved(entry, visibility, removedByUser);
@@ -372,7 +372,7 @@
     private void handleGroupSummaryRemoved(String key) {
         NotificationEntry entry = mNotificationData.get(key);
         if (entry != null && entry.rowExists() && entry.isSummaryWithChildren()) {
-            if (entry.notification.getOverrideGroupKey() != null && !entry.isRowDismissed()) {
+            if (entry.getSbn().getOverrideGroupKey() != null && !entry.isRowDismissed()) {
                 // We don't want to remove children for autobundled notifications as they are not
                 // always cancelled. We only remove them if they were dismissed by the user.
                 return;
@@ -383,7 +383,7 @@
             }
             for (int i = 0; i < childEntries.size(); i++) {
                 NotificationEntry childEntry = childEntries.get(i);
-                boolean isForeground = (entry.notification.getNotification().flags
+                boolean isForeground = (entry.getSbn().getNotification().flags
                         & Notification.FLAG_FOREGROUND_SERVICE) != 0;
                 boolean keepForReply =
                         getRemoteInputManager().shouldKeepForRemoteInputHistory(childEntry)
@@ -421,7 +421,7 @@
 
         abortExistingInflation(key, "addNotification");
         mPendingNotifications.put(key, entry);
-        mNotifLog.log(NotifEvent.NOTIF_ADDED, entry.sbn());
+        mNotifLog.log(NotifEvent.NOTIF_ADDED, entry.getSbn());
         for (NotificationEntryListener listener : mNotificationEntryListeners) {
             listener.onPendingEntryAdded(entry);
         }
@@ -453,7 +453,7 @@
         cancelLifetimeExtension(entry);
 
         mNotificationData.update(entry, ranking, notification, "updateNotificationInternal");
-        mNotifLog.log(NotifEvent.NOTIF_UPDATED, entry.sbn(), entry.ranking());
+        mNotifLog.log(NotifEvent.NOTIF_UPDATED, entry.getSbn(), entry.getRanking());
         for (NotificationEntryListener listener : mNotificationEntryListeners) {
             listener.onPreEntryUpdated(entry);
         }
@@ -507,8 +507,8 @@
         for (NotificationEntry entry : entries) {
             NotificationUiAdjustment adjustment =
                     NotificationUiAdjustment.extractFromNotificationEntry(entry);
-            oldAdjustments.put(entry.key, adjustment);
-            oldImportances.put(entry.key, entry.getImportance());
+            oldAdjustments.put(entry.getKey(), adjustment);
+            oldImportances.put(entry.getKey(), entry.getImportance());
         }
 
         // Populate notification entries from the new rankings.
@@ -519,8 +519,8 @@
         for (NotificationEntry entry : entries) {
             requireBinder().onNotificationRankingUpdated(
                     entry,
-                    oldImportances.get(entry.key),
-                    oldAdjustments.get(entry.key),
+                    oldImportances.get(entry.getKey()),
+                    oldAdjustments.get(entry.getKey()),
                     NotificationUiAdjustment.extractFromNotificationEntry(entry));
         }
 
@@ -538,7 +538,7 @@
         }
         for (NotificationEntry pendingNotification : mPendingNotifications.values()) {
             Ranking ranking = new Ranking();
-            if (rankingMap.getRanking(pendingNotification.key(), ranking)) {
+            if (rankingMap.getRanking(pendingNotification.getKey(), ranking)) {
                 pendingNotification.setRanking(ranking);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
index 5a0b88c..b116409 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
@@ -85,7 +85,7 @@
      * @return true if the provided notification should NOT be shown right now.
      */
     public boolean shouldFilterOut(NotificationEntry entry) {
-        final StatusBarNotification sbn = entry.notification;
+        final StatusBarNotification sbn = entry.getSbn();
         if (!(getEnvironment().isDeviceProvisioned()
                 || showNotificationEvenIfUnprovisioned(sbn))) {
             return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
index eadec6a..7d09932 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
@@ -164,7 +164,7 @@
      * @return true if the entry should bubble up, false otherwise
      */
     public boolean shouldBubbleUp(NotificationEntry entry) {
-        final StatusBarNotification sbn = entry.notification;
+        final StatusBarNotification sbn = entry.getSbn();
 
         if (!canAlertCommon(entry)) {
             return false;
@@ -216,7 +216,7 @@
     }
 
     private boolean shouldHeadsUpWhenAwake(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
 
         if (!mUseHeadsUp) {
             if (DEBUG_HEADS_UP) {
@@ -289,7 +289,7 @@
      * @return true if the entry should ambient pulse, false otherwise
      */
     private boolean shouldHeadsUpWhenDozing(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
 
         if (!mAmbientDisplayConfiguration.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) {
             if (DEBUG_HEADS_UP) {
@@ -336,7 +336,7 @@
      */
     @VisibleForTesting
     public boolean canAlertCommon(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
 
         if (mNotificationFilter.shouldFilterOut(entry)) {
             if (DEBUG || DEBUG_HEADS_UP) {
@@ -363,7 +363,7 @@
      */
     @VisibleForTesting
     public boolean canAlertAwakeCommon(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
 
         if (mPresenter.isDeviceInVrMode()) {
             if (DEBUG_HEADS_UP) {
@@ -423,7 +423,7 @@
      * @return {@code true} if we should launch the full screen intent
      */
     public boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry) {
-        return entry.notification.getNotification().fullScreenIntent != null
+        return entry.getSbn().getNotification().fullScreenIntent != null
             && (!shouldHeadsUp(entry)
                 || mStatusBarStateController.getState() == StatusBarState.KEYGUARD);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
index 970cbf9..533dfb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
@@ -73,7 +73,7 @@
 
         @Override
         public void onBeforeNotificationAdded(NotificationEntry entry) {
-            tagForeground(entry.notification);
+            tagForeground(entry.getSbn());
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index 2f67f90..8a23e37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -37,10 +37,10 @@
 
 @Singleton
 class NotificationWakeUpCoordinator @Inject constructor(
-        private val mContext: Context,
         private val mHeadsUpManagerPhone: HeadsUpManagerPhone,
         private val statusBarStateController: StatusBarStateController,
-        private val bypassController: KeyguardBypassController)
+        private val bypassController: KeyguardBypassController,
+        private val dozeParameters: DozeParameters)
     : OnHeadsUpChangedListener, StatusBarStateController.StateListener,
         PanelExpansionListener {
 
@@ -67,7 +67,6 @@
     private var mVisibilityAmount = 0.0f
     private var mLinearVisibilityAmount = 0.0f
     private val mEntrySetToClearWhenFinished = mutableSetOf<NotificationEntry>()
-    private val mDozeParameters: DozeParameters
     private var pulseExpanding: Boolean = false
     private val wakeUpListeners = arrayListOf<WakeUpListener>()
     private var state: Int = StatusBarState.KEYGUARD
@@ -146,7 +145,6 @@
     init {
         mHeadsUpManagerPhone.addListener(this)
         statusBarStateController.addCallback(this)
-        mDozeParameters = DozeParameters.getInstance(mContext)
         addListener(object : WakeUpListener {
             override fun onFullyHiddenChanged(isFullyHidden: Boolean) {
                 if (isFullyHidden && mNotificationsVisibleForExpansion) {
@@ -377,7 +375,7 @@
     }
 
     private fun shouldAnimateVisibility() =
-            mDozeParameters.getAlwaysOn() && !mDozeParameters.getDisplayNeedsBlanking()
+            dozeParameters.getAlwaysOn() && !dozeParameters.getDisplayNeedsBlanking()
 
     interface WakeUpListener {
         /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java
new file mode 100644
index 0000000..ecce6ea
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java
@@ -0,0 +1,38 @@
+/*
+ * 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.statusbar.notification.collection;
+
+import android.service.notification.NotificationStats.DismissalSentiment;
+import android.service.notification.NotificationStats.DismissalSurface;
+
+import com.android.internal.statusbar.NotificationVisibility;
+
+/** Information that must be supplied when dismissing a notification on the behalf of the user. */
+public class DismissedByUserStats {
+    public final @DismissalSurface int dismissalSurface;
+    public final @DismissalSentiment int dismissalSentiment;
+    public final NotificationVisibility notificationVisibility;
+
+    public DismissedByUserStats(
+            @DismissalSurface int dismissalSurface,
+            @DismissalSentiment int dismissalSentiment,
+            NotificationVisibility notificationVisibility) {
+        this.dismissalSurface = dismissalSurface;
+        this.dismissalSentiment = dismissalSentiment;
+        this.notificationVisibility = notificationVisibility;
+    }
+}
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
new file mode 100644
index 0000000..b551352
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -0,0 +1,426 @@
+/*
+ * 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.statusbar.notification.collection;
+
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_CHANNEL_BANNED;
+import static android.service.notification.NotificationListenerService.REASON_CLICK;
+import static android.service.notification.NotificationListenerService.REASON_ERROR;
+import static android.service.notification.NotificationListenerService.REASON_GROUP_OPTIMIZATION;
+import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
+import static android.service.notification.NotificationListenerService.REASON_LISTENER_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_LISTENER_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_PACKAGE_BANNED;
+import static android.service.notification.NotificationListenerService.REASON_PACKAGE_CHANGED;
+import static android.service.notification.NotificationListenerService.REASON_PACKAGE_SUSPENDED;
+import static android.service.notification.NotificationListenerService.REASON_PROFILE_TURNED_OFF;
+import static android.service.notification.NotificationListenerService.REASON_SNOOZED;
+import static android.service.notification.NotificationListenerService.REASON_TIMEOUT;
+import static android.service.notification.NotificationListenerService.REASON_UNAUTOBUNDLED;
+import static android.service.notification.NotificationListenerService.REASON_USER_STOPPED;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.IntDef;
+import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.RemoteException;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
+import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationListener.NotifServiceListener;
+import com.android.systemui.util.Assert;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Keeps a record of all of the "active" notifications, i.e. the notifications that are currently
+ * posted to the phone. This collection is unsorted, ungrouped, and unfiltered. Just because a
+ * notification appears in this collection doesn't mean that it's currently present in the shade
+ * (notifications can be hidden for a variety of reasons). Code that cares about what notifications
+ * are *visible* right now should register listeners later in the pipeline.
+ *
+ * Each notification is represented by a {@link NotificationEntry}, which is itself made up of two
+ * parts: a {@link StatusBarNotification} and a {@link Ranking}. When notifications are updated,
+ * their underlying SBNs and Rankings are swapped out, but the enclosing NotificationEntry (and its
+ * associated key) remain the same. In general, an SBN can only be updated when the notification is
+ * reposted by the source app; Rankings are updated much more often, usually every time there is an
+ * update from any kind from NotificationManager.
+ *
+ * In general, this collection closely mirrors the list maintained by NotificationManager, but it
+ * can occasionally diverge due to lifetime extenders (see
+ * {@link #addNotificationLifetimeExtender(NotifLifetimeExtender)}).
+ *
+ * Interested parties can register listeners
+ * ({@link #addCollectionListener(NotifCollectionListener)}) to be informed when notifications are
+ * added, updated, or removed.
+ */
+@MainThread
+@Singleton
+public class NotifCollection {
+    private final IStatusBarService mStatusBarService;
+
+    private final Map<String, NotificationEntry> mNotificationSet = new ArrayMap<>();
+    private final Collection<NotificationEntry> mReadOnlyNotificationSet =
+            Collections.unmodifiableCollection(mNotificationSet.values());
+
+    @Nullable private NotifListBuilder mListBuilder;
+    private final List<NotifCollectionListener> mNotifCollectionListeners = new ArrayList<>();
+    private final List<NotifLifetimeExtender> mLifetimeExtenders = new ArrayList<>();
+
+    private boolean mAttached = false;
+    private boolean mAmDispatchingToOtherCode;
+
+    @Inject
+    public NotifCollection(IStatusBarService statusBarService) {
+        Assert.isMainThread();
+        mStatusBarService = statusBarService;
+    }
+
+    /** Initializes the NotifCollection and registers it to receive notification events. */
+    public void attach(NotificationListener listenerService) {
+        Assert.isMainThread();
+        if (mAttached) {
+            throw new RuntimeException("attach() called twice");
+        }
+        mAttached = true;
+
+        listenerService.setDownstreamListener(mNotifServiceListener);
+    }
+
+    /**
+     * Sets the class responsible for converting the collection into the list of currently-visible
+     * notifications.
+     */
+    public void setListBuilder(NotifListBuilder listBuilder) {
+        Assert.isMainThread();
+        mListBuilder = listBuilder;
+    }
+
+    /**
+     * Returns the list of "active" notifications, i.e. the notifications that are currently posted
+     * to the phone. In general, this tracks closely to the list maintained by NotificationManager,
+     * but it can diverge slightly due to lifetime extenders.
+     *
+     * The returned list is read-only, unsorted, unfiltered, and ungrouped.
+     */
+    public Collection<NotificationEntry> getNotifs() {
+        Assert.isMainThread();
+        return mReadOnlyNotificationSet;
+    }
+
+    /**
+     * Registers a listener to be informed when notifications are added, removed or updated.
+     */
+    public void addCollectionListener(NotifCollectionListener listener) {
+        Assert.isMainThread();
+        mNotifCollectionListeners.add(listener);
+    }
+
+    /**
+     * Registers a lifetime extender. Lifetime extenders can cause notifications that have been
+     * dismissed or retracted to be temporarily retained in the collection.
+     */
+    public void addNotificationLifetimeExtender(NotifLifetimeExtender extender) {
+        Assert.isMainThread();
+        checkForReentrantCall();
+        if (mLifetimeExtenders.contains(extender)) {
+            throw new IllegalArgumentException("Extender " + extender + " already added.");
+        }
+        mLifetimeExtenders.add(extender);
+        extender.setCallback(this::onEndLifetimeExtension);
+    }
+
+    /**
+     * Dismiss a notification on behalf of the user.
+     */
+    public void dismissNotification(
+            NotificationEntry entry,
+            @CancellationReason int reason,
+            @NonNull DismissedByUserStats stats) {
+        Assert.isMainThread();
+        checkNotNull(stats);
+        checkForReentrantCall();
+
+        removeNotification(entry.getKey(), null, reason, stats);
+    }
+
+    private void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
+        Assert.isMainThread();
+
+        NotificationEntry entry = mNotificationSet.get(sbn.getKey());
+
+        if (entry == null) {
+            // A new notification!
+            Log.d(TAG, "POSTED  " + sbn.getKey());
+
+            entry = new NotificationEntry(sbn, requireRanking(rankingMap, sbn.getKey()));
+            mNotificationSet.put(sbn.getKey(), entry);
+            applyRanking(rankingMap);
+
+            dispatchOnEntryAdded(entry);
+
+        } else {
+            // Update to an existing entry
+            Log.d(TAG, "UPDATED " + sbn.getKey());
+
+            // Notification is updated so it is essentially re-added and thus alive again.  Don't
+            // need to keep its lifetime extended.
+            cancelLifetimeExtension(entry);
+
+            entry.setSbn(sbn);
+            applyRanking(rankingMap);
+
+            dispatchOnEntryUpdated(entry);
+        }
+
+        rebuildList();
+    }
+
+    private void onNotificationRemoved(
+            StatusBarNotification sbn,
+            @Nullable RankingMap rankingMap,
+            int reason) {
+        Assert.isMainThread();
+        Log.d(TAG, "REMOVED " + sbn.getKey() + " reason=" + reason);
+        removeNotification(sbn.getKey(), rankingMap, reason, null);
+    }
+
+    private void onNotificationRankingUpdate(RankingMap rankingMap) {
+        Assert.isMainThread();
+        applyRanking(rankingMap);
+        rebuildList();
+    }
+
+    private void removeNotification(
+            String key,
+            @Nullable RankingMap rankingMap,
+            @CancellationReason int reason,
+            DismissedByUserStats dismissedByUserStats) {
+
+        NotificationEntry entry = mNotificationSet.get(key);
+        if (entry == null) {
+            throw new IllegalStateException("No notification to remove with key " + key);
+        }
+
+        entry.mLifetimeExtenders.clear();
+        mAmDispatchingToOtherCode = true;
+        for (NotifLifetimeExtender extender : mLifetimeExtenders) {
+            if (extender.shouldExtendLifetime(entry, reason)) {
+                entry.mLifetimeExtenders.add(extender);
+            }
+        }
+        mAmDispatchingToOtherCode = false;
+
+        if (!isLifetimeExtended(entry)) {
+            mNotificationSet.remove(entry.getKey());
+
+            if (dismissedByUserStats != null) {
+                try {
+                    mStatusBarService.onNotificationClear(
+                            entry.getSbn().getPackageName(),
+                            entry.getSbn().getTag(),
+                            entry.getSbn().getId(),
+                            entry.getSbn().getUser().getIdentifier(),
+                            entry.getSbn().getKey(),
+                            dismissedByUserStats.dismissalSurface,
+                            dismissedByUserStats.dismissalSentiment,
+                            dismissedByUserStats.notificationVisibility);
+                } catch (RemoteException e) {
+                    // system process is dead if we're here.
+                }
+            }
+
+            if (rankingMap != null) {
+                applyRanking(rankingMap);
+            }
+
+            dispatchOnEntryRemoved(entry, reason, dismissedByUserStats != null /* removedByUser */);
+        }
+
+        rebuildList();
+    }
+
+    private void applyRanking(RankingMap rankingMap) {
+        for (NotificationEntry entry : mNotificationSet.values()) {
+            if (!isLifetimeExtended(entry)) {
+                Ranking ranking = requireRanking(rankingMap, entry.getKey());
+                entry.setRanking(ranking);
+            }
+        }
+    }
+
+    private void rebuildList() {
+        if (mListBuilder != null) {
+            mListBuilder.onBuildList(mReadOnlyNotificationSet);
+        }
+    }
+
+    private void onEndLifetimeExtension(NotifLifetimeExtender extender, NotificationEntry entry) {
+        Assert.isMainThread();
+        if (!mAttached) {
+            return;
+        }
+        checkForReentrantCall();
+
+        if (!entry.mLifetimeExtenders.remove(extender)) {
+            throw new IllegalStateException(
+                    String.format(
+                            "Cannot end lifetime extension for extender \"%s\" (%s)",
+                            extender.getName(),
+                            extender));
+        }
+
+        if (!isLifetimeExtended(entry)) {
+            // TODO: This doesn't need to be undefined -- we can set either EXTENDER_EXPIRED or
+            // save the original reason
+            removeNotification(entry.getKey(), null, REASON_UNKNOWN, null);
+        }
+    }
+
+    private void cancelLifetimeExtension(NotificationEntry entry) {
+        mAmDispatchingToOtherCode = true;
+        for (NotifLifetimeExtender extender : entry.mLifetimeExtenders) {
+            extender.cancelLifetimeExtension(entry);
+        }
+        mAmDispatchingToOtherCode = false;
+        entry.mLifetimeExtenders.clear();
+    }
+
+    private boolean isLifetimeExtended(NotificationEntry entry) {
+        return entry.mLifetimeExtenders.size() > 0;
+    }
+
+    private void checkForReentrantCall() {
+        if (mAmDispatchingToOtherCode) {
+            throw new IllegalStateException("Reentrant call detected");
+        }
+    }
+
+    private static Ranking requireRanking(RankingMap rankingMap, String key) {
+        // TODO: Modify RankingMap so that we don't have to make a copy here
+        Ranking ranking = new Ranking();
+        if (!rankingMap.getRanking(key, ranking)) {
+            throw new IllegalArgumentException("Ranking map doesn't contain key: " + key);
+        }
+        return ranking;
+    }
+
+    private void dispatchOnEntryAdded(NotificationEntry entry) {
+        mAmDispatchingToOtherCode = true;
+        if (mListBuilder != null) {
+            mListBuilder.onBeginDispatchToListeners();
+        }
+        for (NotifCollectionListener listener : mNotifCollectionListeners) {
+            listener.onEntryAdded(entry);
+        }
+        mAmDispatchingToOtherCode = false;
+    }
+
+    private void dispatchOnEntryUpdated(NotificationEntry entry) {
+        mAmDispatchingToOtherCode = true;
+        if (mListBuilder != null) {
+            mListBuilder.onBeginDispatchToListeners();
+        }
+        for (NotifCollectionListener listener : mNotifCollectionListeners) {
+            listener.onEntryUpdated(entry);
+        }
+        mAmDispatchingToOtherCode = false;
+    }
+
+    private void dispatchOnEntryRemoved(
+            NotificationEntry entry,
+            @CancellationReason int reason,
+            boolean removedByUser) {
+        mAmDispatchingToOtherCode = true;
+        if (mListBuilder != null) {
+            mListBuilder.onBeginDispatchToListeners();
+        }
+        for (NotifCollectionListener listener : mNotifCollectionListeners) {
+            listener.onEntryRemoved(entry, reason, removedByUser);
+        }
+        mAmDispatchingToOtherCode = false;
+    }
+
+    private final NotifServiceListener mNotifServiceListener = new NotifServiceListener() {
+        @Override
+        public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
+            NotifCollection.this.onNotificationPosted(sbn, rankingMap);
+        }
+
+        @Override
+        public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
+            NotifCollection.this.onNotificationRemoved(sbn, rankingMap, REASON_UNKNOWN);
+        }
+
+        @Override
+        public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
+                int reason) {
+            NotifCollection.this.onNotificationRemoved(sbn, rankingMap, reason);
+        }
+
+        @Override
+        public void onNotificationRankingUpdate(RankingMap rankingMap) {
+            NotifCollection.this.onNotificationRankingUpdate(rankingMap);
+        }
+    };
+
+    private static final String TAG = "NotifCollection";
+
+    @IntDef(prefix = { "REASON_" }, value = {
+            REASON_UNKNOWN,
+            REASON_CLICK,
+            REASON_CANCEL_ALL,
+            REASON_ERROR,
+            REASON_PACKAGE_CHANGED,
+            REASON_USER_STOPPED,
+            REASON_PACKAGE_BANNED,
+            REASON_APP_CANCEL,
+            REASON_APP_CANCEL_ALL,
+            REASON_LISTENER_CANCEL,
+            REASON_LISTENER_CANCEL_ALL,
+            REASON_GROUP_SUMMARY_CANCELED,
+            REASON_GROUP_OPTIMIZATION,
+            REASON_PACKAGE_SUSPENDED,
+            REASON_PROFILE_TURNED_OFF,
+            REASON_UNAUTOBUNDLED,
+            REASON_CHANNEL_BANNED,
+            REASON_SNOOZED,
+            REASON_TIMEOUT,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface CancellationReason {}
+
+    public static final int REASON_UNKNOWN = 0;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java
new file mode 100644
index 0000000..032620e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java
@@ -0,0 +1,46 @@
+/*
+ * 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.statusbar.notification.collection;
+
+import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+
+/**
+ * Listener interface for {@link NotifCollection}.
+ */
+public interface NotifCollectionListener {
+    /**
+     * Called whenever a notification with a new key is posted.
+     */
+    default void onEntryAdded(NotificationEntry entry) {
+    }
+
+    /**
+     * Called whenever a notification with the same key as an existing notification is posted. By
+     * the time this listener is called, the entry's SBN and Ranking will already have been updated.
+     */
+    default void onEntryUpdated(NotificationEntry entry) {
+    }
+
+    /**
+     * Called immediately after a notification has been removed from the collection.
+     */
+    default void onEntryRemoved(
+            NotificationEntry entry,
+            @CancellationReason int reason,
+            boolean removedByUser) {
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java
new file mode 100644
index 0000000..2c7b138
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection;
+
+import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+
+/**
+ * A way for other code to temporarily extend the lifetime of a notification after it has been
+ * retracted. See {@link NotifCollection#addNotificationLifetimeExtender(NotifLifetimeExtender)}.
+ */
+public interface NotifLifetimeExtender {
+    /** Name to associate with this extender (for the purposes of debugging) */
+    String getName();
+
+    /**
+     * Called on the extender immediately after it has been registered. The extender should hang on
+     * to this callback and execute it whenever it no longer needs to extend the lifetime of a
+     * notification.
+     */
+    void setCallback(OnEndLifetimeExtensionCallback callback);
+
+    /**
+     * Called by the NotifCollection whenever a notification has been retracted (by the app) or
+     * dismissed (by the user). If the extender returns true, it is considered to be extending the
+     * lifetime of that notification. Lifetime-extended notifications are kept around until all
+     * active extenders expire their extension by calling onEndLifetimeExtension(). This method is
+     * called on all lifetime extenders even if earlier ones return true (in other words, multiple
+     * lifetime extenders can be extending a notification at the same time).
+     */
+    boolean shouldExtendLifetime(NotificationEntry entry, @CancellationReason int reason);
+
+    /**
+     * Called by the NotifCollection to inform a lifetime extender that its extension of a notif
+     * is no longer valid (usually because the notif has been reposted and so no longer needs
+     * lifetime extension). The extender should clean up any references it has to the notif in
+     * question.
+     */
+    void cancelLifetimeExtension(NotificationEntry entry);
+
+    /** Callback for notifying the NotifCollection that a lifetime extension has expired. */
+    interface OnEndLifetimeExtensionCallback {
+        void onEndLifetimeExtension(NotifLifetimeExtender extender, NotificationEntry entry);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilder.java
new file mode 100644
index 0000000..17fef68
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilder.java
@@ -0,0 +1,43 @@
+/*
+ * 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.statusbar.notification.collection;
+
+import java.util.Collection;
+
+/**
+ * Interface for the class responsible for converting a NotifCollection into the final sorted,
+ * filtered, and grouped list of currently visible notifications.
+ */
+public interface NotifListBuilder {
+    /**
+     * Called after the NotifCollection has received an update from NotificationManager but before
+     * it dispatches any change events to its listeners. This is to inform the list builder that
+     * the first stage of the pipeline has been triggered. After events have been dispatched,
+     * onBuildList() will be called.
+     *
+     * While onBuildList() is always called after this method is called, the converse is not always
+     * true: sometimes the NotifCollection applies an update that does not need to dispatch events,
+     * in which case this method will be skipped and onBuildList will be called directly.
+     */
+    void onBeginDispatchToListeners();
+
+    /**
+     * Called by the NotifCollection to indicate that something in the collection has changed and
+     * that the list builder should regenerate the list.
+     */
+    void onBuildList(Collection<NotificationEntry> entries);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
index a98fa66..623ccca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
@@ -93,10 +93,10 @@
             new Comparator<NotificationEntry>() {
         @Override
         public int compare(NotificationEntry a, NotificationEntry b) {
-            final StatusBarNotification na = a.notification;
-            final StatusBarNotification nb = b.notification;
-            int aRank = getRank(a.key);
-            int bRank = getRank(b.key);
+            final StatusBarNotification na = a.getSbn();
+            final StatusBarNotification nb = b.getSbn();
+            int aRank = getRank(a.getKey());
+            int bRank = getRank(b.getKey());
 
             boolean aMedia = isImportantMedia(a);
             boolean bMedia = isImportantMedia(b);
@@ -164,7 +164,7 @@
             final int len = mEntries.size();
             for (int i = 0; i < len; i++) {
                 NotificationEntry entry = mEntries.valueAt(i);
-                final StatusBarNotification sbn = entry.notification;
+                final StatusBarNotification sbn = entry.getSbn();
                 if (!getEnvironment().isNotificationForCurrentProfiles(sbn)) {
                     continue;
                 }
@@ -180,11 +180,11 @@
 
     public void add(NotificationEntry entry) {
         synchronized (mEntries) {
-            mEntries.put(entry.notification.getKey(), entry);
+            mEntries.put(entry.getSbn().getKey(), entry);
         }
         mGroupManager.onEntryAdded(entry);
 
-        updateRankingAndSort(mRankingMap, "addEntry=" + entry.sbn());
+        updateRankingAndSort(mRankingMap, "addEntry=" + entry.getSbn());
     }
 
     public NotificationEntry remove(String key, RankingMap ranking) {
@@ -194,7 +194,7 @@
         }
         if (removed == null) return null;
         mGroupManager.onEntryRemoved(removed);
-        updateRankingAndSort(ranking, "removeEntry=" + removed.sbn());
+        updateRankingAndSort(ranking, "removeEntry=" + removed.getSbn());
         return removed;
     }
 
@@ -205,8 +205,8 @@
             StatusBarNotification notification,
             String reason) {
         updateRanking(ranking, reason);
-        final StatusBarNotification oldNotification = entry.notification;
-        entry.setNotification(notification);
+        final StatusBarNotification oldNotification = entry.getSbn();
+        entry.setSbn(notification);
         mGroupManager.onEntryUpdated(entry, oldNotification);
     }
 
@@ -222,9 +222,9 @@
             final int len = mEntries.size();
             for (int i = 0; i < len; i++) {
                 NotificationEntry entry = mEntries.valueAt(i);
-                if (uid == entry.notification.getUid()
-                        && pkg.equals(entry.notification.getPackageName())
-                        && key.equals(entry.key)) {
+                if (uid == entry.getSbn().getUid()
+                        && pkg.equals(entry.getSbn().getPackageName())
+                        && key.equals(entry.getKey())) {
                     if (showIcon) {
                         entry.mActiveAppOps.add(appOp);
                     } else {
@@ -251,7 +251,7 @@
                 final ArrayList<NotificationEntry> logicalChildren =
                         mGroupManager.getLogicalChildren(statusBarNotification);
                 for (NotificationEntry child : logicalChildren) {
-                    if (isHighPriority(child.notification)) {
+                    if (isHighPriority(child.getSbn())) {
                         return true;
                     }
                 }
@@ -338,17 +338,17 @@
     }
 
     private boolean isImportantMedia(NotificationEntry e) {
-        int importance = e.ranking().getImportance();
-        boolean media = e.key.equals(getMediaManager().getMediaNotificationKey())
+        int importance = e.getRanking().getImportance();
+        boolean media = e.getKey().equals(getMediaManager().getMediaNotificationKey())
                 && importance > NotificationManager.IMPORTANCE_MIN;
 
         return media;
     }
 
     private boolean isSystemMax(NotificationEntry e) {
-        int importance = e.ranking().getImportance();
+        int importance = e.getRanking().getImportance();
         boolean sys = importance  >= NotificationManager.IMPORTANCE_HIGH
-                && isSystemNotification(e.notification);
+                && isSystemNotification(e.getSbn());
 
         return sys;
     }
@@ -369,18 +369,18 @@
                 for (int i = 0; i < len; i++) {
                     NotificationEntry entry = mEntries.valueAt(i);
                     Ranking newRanking = new Ranking();
-                    if (!getRanking(entry.key, newRanking)) {
+                    if (!getRanking(entry.getKey(), newRanking)) {
                         continue;
                     }
                     entry.setRanking(newRanking);
 
-                    final StatusBarNotification oldSbn = entry.notification.cloneLight();
+                    final StatusBarNotification oldSbn = entry.getSbn().cloneLight();
                     final String overrideGroupKey = newRanking.getOverrideGroupKey();
                     if (!Objects.equals(oldSbn.getOverrideGroupKey(), overrideGroupKey)) {
-                        entry.notification.setOverrideGroupKey(overrideGroupKey);
+                        entry.getSbn().setOverrideGroupKey(overrideGroupKey);
                         mGroupManager.onEntryUpdated(entry, oldSbn);
                     }
-                    entry.setIsHighPriority(isHighPriority(entry.notification));
+                    entry.setIsHighPriority(isHighPriority(entry.getSbn()));
                 }
             }
         }
@@ -481,10 +481,10 @@
     }
 
     private void dumpEntry(PrintWriter pw, String indent, int i, NotificationEntry e) {
-        getRanking(e.key, mTmpRanking);
+        getRanking(e.getKey(), mTmpRanking);
         pw.print(indent);
-        pw.println("  [" + i + "] key=" + e.key + " icon=" + e.icon);
-        StatusBarNotification n = e.notification;
+        pw.println("  [" + i + "] key=" + e.getKey() + " icon=" + e.icon);
+        StatusBarNotification n = e.getSbn();
         pw.print(indent);
         pw.println("      pkg=" + n.getPackageName() + " id=" + n.getId() + " importance="
                 + mTmpRanking.getImportance());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index c3211e3..e004ca7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -30,6 +30,7 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
 
+import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING;
 
 import android.annotation.NonNull;
@@ -90,10 +91,24 @@
     private static final long NOT_LAUNCHED_YET = -LAUNCH_COOLDOWN;
     private static final int COLOR_INVALID = 1;
 
-    public final String key;
-    public StatusBarNotification notification;
+    private final String mKey;
+    private StatusBarNotification mSbn;
     private Ranking mRanking;
 
+
+    /*
+     * Bookkeeping members
+     */
+
+    /** List of lifetime extenders that are extending the lifetime of this notification. */
+    final List<NotifLifetimeExtender> mLifetimeExtenders = new ArrayList<>();
+
+
+    /*
+    * Old members
+    * TODO: Remove every member beneath this line if possible
+    */
+
     public boolean noisy;
     public StatusBarIconView icon;
     public StatusBarIconView expandedIcon;
@@ -161,34 +176,42 @@
     public NotificationEntry(
             @NonNull StatusBarNotification sbn,
             @NonNull Ranking ranking) {
-        this.key = sbn.getKey();
-        setNotification(sbn);
+        checkNotNull(sbn);
+        checkNotNull(sbn.getKey());
+        checkNotNull(ranking);
+
+        mKey = sbn.getKey();
+        setSbn(sbn);
         setRanking(ranking);
     }
 
     /** The key for this notification. Guaranteed to be immutable and unique */
-    public String key() {
-        return key;
+    public String getKey() {
+        return mKey;
     }
 
     /**
      * The StatusBarNotification that represents one half of a NotificationEntry (the other half
      * being the Ranking). This object is swapped out whenever a notification is updated.
      */
-    public StatusBarNotification sbn() {
-        return notification;
+    public StatusBarNotification getSbn() {
+        return mSbn;
     }
 
     /**
      * Should only be called by NotificationEntryManager and friends.
      * TODO: Make this package-private
      */
-    public void setNotification(StatusBarNotification sbn) {
-        if (sbn.getKey() != null && key != null && !sbn.getKey().equals(key)) {
+    public void setSbn(@NonNull StatusBarNotification sbn) {
+        checkNotNull(sbn);
+        checkNotNull(sbn.getKey());
+
+        if (!sbn.getKey().equals(mKey)) {
             throw new IllegalArgumentException("New key " + sbn.getKey()
-                    + " doesn't match existing key " + key);
+                    + " doesn't match existing key " + mKey);
         }
-        notification = sbn;
+
+        mSbn = sbn;
         updatePeopleList();
     }
 
@@ -197,7 +220,7 @@
      * StatusBarNotification). This object is swapped out whenever a the ranking is updated (which
      * generally occurs whenever anything changes in the notification list).
      */
-    public Ranking ranking() {
+    public Ranking getRanking() {
         return mRanking;
     }
 
@@ -206,9 +229,12 @@
      * TODO: Make this package-private
      */
     public void setRanking(@NonNull Ranking ranking) {
-        if (!ranking.getKey().equals(key)) {
+        checkNotNull(ranking);
+        checkNotNull(ranking.getKey());
+
+        if (!ranking.getKey().equals(mKey)) {
             throw new IllegalArgumentException("New key " + ranking.getKey()
-                    + " doesn't match existing key " + key);
+                    + " doesn't match existing key " + mKey);
         }
         mRanking = ranking;
         isVisuallyInterruptive = ranking.visuallyInterruptive();
@@ -278,13 +304,13 @@
     }
 
     public boolean isBubble() {
-        return (notification.getNotification().flags & FLAG_BUBBLE) != 0;
+        return (mSbn.getNotification().flags & FLAG_BUBBLE) != 0;
     }
 
     private void updatePeopleList() {
         mAssociatedPeople.clear();
 
-        Bundle extras = notification.getNotification().extras;
+        Bundle extras = mSbn.getNotification().extras;
         if (extras == null) {
             return;
         }
@@ -296,7 +322,7 @@
         }
 
         if (Notification.MessagingStyle.class.equals(
-                notification.getNotification().getNotificationStyle())) {
+                mSbn.getNotification().getNotificationStyle())) {
             final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES);
             if (!ArrayUtils.isEmpty(messages)) {
                 for (Notification.MessagingStyle.Message message :
@@ -316,7 +342,7 @@
      * Returns the data needed for a bubble for this notification, if it exists.
      */
     public Notification.BubbleMetadata getBubbleMetadata() {
-        return notification.getNotification().getBubbleMetadata();
+        return mSbn.getNotification().getBubbleMetadata();
     }
 
     /**
@@ -438,7 +464,7 @@
                 });
 
         // Construct the centered icon
-        if (notification.getNotification().isMediaNotification()) {
+        if (mSbn.getNotification().isMediaNotification()) {
             centeredIcon = new StatusBarIconView(context,
                     sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
             centeredIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
@@ -478,8 +504,8 @@
             // Update the icon
             Notification n = sbn.getNotification();
             final StatusBarIcon ic = new StatusBarIcon(
-                    notification.getUser(),
-                    notification.getPackageName(),
+                    mSbn.getUser(),
+                    mSbn.getPackageName(),
                     n.getSmallIcon(),
                     n.iconLevel,
                     n.number,
@@ -503,7 +529,7 @@
     public int getContrastedColor(Context context, boolean isLowPriority,
             int backgroundColor) {
         int rawColor = isLowPriority ? Notification.COLOR_DEFAULT :
-                notification.getNotification().color;
+                mSbn.getNotification().color;
         if (mCachedContrastColorIsFor == rawColor && mCachedContrastColor != COLOR_INVALID) {
             return mCachedContrastColor;
         }
@@ -569,7 +595,7 @@
         if (!hasSentReply) {
             return false;
         }
-        Bundle extras = notification.getNotification().extras;
+        Bundle extras = mSbn.getNotification().extras;
         CharSequence[] replyTexts = extras.getCharSequenceArray(
                 Notification.EXTRA_REMOTE_INPUT_HISTORY);
         if (!ArrayUtils.isEmpty(replyTexts)) {
@@ -771,7 +797,7 @@
      * @see #canViewBeDismissed()
      */
     public boolean isClearable() {
-        if (notification == null || !notification.isClearable()) {
+        if (!mSbn.isClearable()) {
             return false;
         }
 
@@ -794,15 +820,15 @@
 
     @VisibleForTesting
     boolean isExemptFromDndVisualSuppression() {
-        if (isNotificationBlockedByPolicy(notification.getNotification())) {
+        if (isNotificationBlockedByPolicy(mSbn.getNotification())) {
             return false;
         }
 
-        if ((notification.getNotification().flags
+        if ((mSbn.getNotification().flags
                 & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
             return true;
         }
-        if (notification.getNotification().isMediaNotification()) {
+        if (mSbn.getNotification().isMediaNotification()) {
             return true;
         }
         if (mIsSystemNotification != null && mIsSystemNotification) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
index e5571b6..5dbb9c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
@@ -135,9 +135,9 @@
             throws InflationException {
         ViewGroup parent = mListContainer.getViewParentForNotification(entry);
         PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
-                entry.notification.getUser().getIdentifier());
+                entry.getSbn().getUser().getIdentifier());
 
-        final StatusBarNotification sbn = entry.notification;
+        final StatusBarNotification sbn = entry.getSbn();
         if (entry.rowExists()) {
             entry.updateIcons(mContext, sbn);
             entry.reset();
@@ -156,7 +156,7 @@
     private void bindRow(NotificationEntry entry, PackageManager pmUser,
             StatusBarNotification sbn, ExpandableNotificationRow row,
             Runnable onDismissRunnable) {
-        row.setExpansionLogger(mExpansionLogger, entry.notification.getKey());
+        row.setExpansionLogger(mExpansionLogger, entry.getSbn().getKey());
         row.setBypassController(mKeyguardBypassController);
         row.setStatusBarStateController(mStatusBarStateController);
         row.setGroupManager(mGroupManager);
@@ -213,8 +213,8 @@
                 entry.reset();
                 PackageManager pmUser = StatusBar.getPackageManagerForUser(
                         mContext,
-                        entry.notification.getUser().getIdentifier());
-                updateNotification(entry, pmUser, entry.notification, entry.getRow());
+                        entry.getSbn().getUser().getIdentifier());
+                updateNotification(entry, pmUser, entry.getSbn(), entry.getRow());
             } else {
                 // Once the RowInflaterTask is done, it will pick up the updated entry, so
                 // no-op here.
@@ -248,7 +248,7 @@
 
         // TODO: should updates to the entry be happening somewhere else?
         entry.setIconTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
-        entry.autoRedacted = entry.notification.getNotification().publicVersion == null;
+        entry.autoRedacted = entry.getSbn().getNotification().publicVersion == null;
 
         entry.setRow(row);
         row.setOnActivatedListener(mPresenter);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
index 7703cbd..8ebbca2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
@@ -27,12 +27,11 @@
 
 /**
  * An event related to notifications. {@link NotifLog} stores and prints these events for debugging
- * and triaging purposes.
+ * and triaging purposes. We do not store a copy of the status bar notification nor ranking
+ * here to mitigate memory usage.
  */
 public class NotifEvent extends RichEvent {
     public static final int TOTAL_EVENT_TYPES = 11;
-    private final StatusBarNotification mSbn;
-    private final Ranking mRanking;
 
     /**
      * Creates a NotifEvent with an event type that matches with an index in the array
@@ -44,34 +43,20 @@
     public NotifEvent(int logLevel, int type, String reason, StatusBarNotification sbn,
             Ranking ranking) {
         super(logLevel, type, reason);
+        mMessage += getExtraInfo(sbn, ranking);
+    }
+
+    private String getExtraInfo(StatusBarNotification sbn, Ranking ranking) {
+        StringBuilder extraInfo = new StringBuilder();
 
         if (sbn != null) {
-            mSbn = sbn.cloneLight();
-        } else {
-            mSbn = null;
+            extraInfo.append(" Sbn=");
+            extraInfo.append(sbn);
         }
 
         if (ranking != null) {
-            mRanking = new Ranking();
-            mRanking.populate(ranking);
-        } else {
-            mRanking = null;
-        }
-
-        mMessage += getExtraInfo();
-    }
-
-    private String getExtraInfo() {
-        StringBuilder extraInfo = new StringBuilder();
-
-        if (mSbn != null) {
-            extraInfo.append(" Sbn=");
-            extraInfo.append(mSbn);
-        }
-
-        if (mRanking != null) {
             extraInfo.append(" Ranking=");
-            extraInfo.append(mRanking);
+            extraInfo.append(ranking);
         }
 
         return extraInfo.toString();
@@ -107,13 +92,6 @@
     }
 
     /**
-     * @return a copy of the status bar notification that changed with this event
-     */
-    public StatusBarNotification getSbn() {
-        return mSbn;
-    }
-
-    /**
      * Builds a NotifEvent.
      */
     public static class NotifEventBuilder extends RichEvent.Builder<NotifEventBuilder> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java
index 8466d2e8..1292831 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java
@@ -111,7 +111,7 @@
      * @return true if successfully logged, else false
      */
     public boolean log(@NotifEvent.EventType int eventType, NotificationEntry entry) {
-        return log(eventType, entry.sbn(), entry.ranking(), "");
+        return log(eventType, entry.getSbn(), entry.getRanking(), "");
     }
 
     /**
@@ -120,6 +120,6 @@
      */
     public boolean log(@NotifEvent.EventType int eventType, NotificationEntry entry,
             String msg) {
-        return log(eventType, entry.sbn(), entry.ranking(), msg);
+        return log(eventType, entry.getSbn(), entry.getRanking(), msg);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 81275fd..b7f408e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -126,7 +126,7 @@
             int N = activeNotifications.size();
             for (int i = 0; i < N; i++) {
                 NotificationEntry entry = activeNotifications.get(i);
-                String key = entry.notification.getKey();
+                String key = entry.getSbn().getKey();
                 boolean isVisible = mListContainer.isInVisibleLocation(entry);
                 NotificationVisibility visObj = NotificationVisibility.obtain(key, i, N, isVisible,
                         getNotificationLocation(entry));
@@ -214,14 +214,14 @@
                     NotificationVisibility visibility,
                     boolean removedByUser) {
                 if (removedByUser && visibility != null) {
-                    logNotificationClear(entry.key, entry.notification, visibility);
+                    logNotificationClear(entry.getKey(), entry.getSbn(), visibility);
                 }
-                mExpansionStateLogger.onEntryRemoved(entry.key);
+                mExpansionStateLogger.onEntryRemoved(entry.getKey());
             }
 
             @Override
             public void onEntryReinflated(NotificationEntry entry) {
-                mExpansionStateLogger.onEntryReinflated(entry.key);
+                mExpansionStateLogger.onEntryReinflated(entry.getKey());
             }
 
             @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 924a347..536db67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -442,7 +442,7 @@
      */
     public void setEntry(@NonNull NotificationEntry entry) {
         mEntry = entry;
-        mStatusBarNotification = entry.notification;
+        mStatusBarNotification = entry.getSbn();
         cacheIsSystemNotification();
     }
 
@@ -1203,7 +1203,7 @@
         // Let's update our childrencontainer. This is intentionally not guarded with
         // mIsSummaryWithChildren since we might have had children but not anymore.
         if (mChildrenContainer != null) {
-            mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.notification);
+            mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.getSbn());
         }
         if (mGuts != null) {
             NotificationGuts oldGuts = mGuts;
@@ -2303,7 +2303,7 @@
 
     private void updateRippleAllowed() {
         boolean allowed = isOnKeyguard()
-                || mEntry.notification.getNotification().contentIntent == null;
+                || mEntry.getSbn().getNotification().contentIntent == null;
         setRippleAllowed(allowed);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index a612a17..a91a119 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -230,7 +230,7 @@
         }
         // Only inflate the ones that are set.
         reInflateFlags &= mInflationFlags;
-        StatusBarNotification sbn = mRow.getEntry().notification;
+        StatusBarNotification sbn = mRow.getEntry().getSbn();
 
         // To check if the notification has inline image and preload inline image if necessary.
         mRow.getImageResolver().preloadImages(sbn.getNotification());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index f30a8b1..b12c76c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -1097,7 +1097,7 @@
     }
 
     public void onNotificationUpdated(NotificationEntry entry) {
-        mStatusBarNotification = entry.notification;
+        mStatusBarNotification = entry.getSbn();
         mOnContentViewInactiveListeners.clear();
         mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
         updateAllSingleLineViews();
@@ -1179,7 +1179,7 @@
                 : mHeadsUpInflatedSmartReplies.getSmartRepliesAndActions();
         if (DEBUG) {
             Log.d(TAG, String.format("Adding suggestions for %s, %d actions, and %d replies.",
-                    entry.notification.getKey(),
+                    entry.getSbn().getKey(),
                     mCurrentSmartRepliesAndActions.smartActions == null ? 0 :
                             mCurrentSmartRepliesAndActions.smartActions.actions.size(),
                     mCurrentSmartRepliesAndActions.smartReplies == null ? 0 :
@@ -1253,7 +1253,7 @@
                 }
             }
             if (hasRemoteInput) {
-                int color = entry.notification.getNotification().color;
+                int color = entry.getSbn().getNotification().color;
                 if (color == Notification.COLOR_DEFAULT) {
                     color = mContext.getColor(R.color.default_remote_input_background);
                 }
@@ -1267,7 +1267,7 @@
                 if (existingPendingIntent != null || existing.isActive()) {
                     // The current action could be gone, or the pending intent no longer valid.
                     // If we find a matching action in the new notification, focus, otherwise close.
-                    Notification.Action[] actions = entry.notification.getNotification().actions;
+                    Notification.Action[] actions = entry.getSbn().getNotification().actions;
                     if (existingPendingIntent != null) {
                         existing.setPendingIntent(existingPendingIntent);
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 2b7deec..1de2cbb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -494,15 +494,17 @@
     @Override
     public void setShouldManageLifetime(NotificationEntry entry, boolean shouldExtend) {
         if (shouldExtend) {
-            mKeyToRemoveOnGutsClosed = entry.key;
+            mKeyToRemoveOnGutsClosed = entry.getKey();
             if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "Keeping notification because it's showing guts. " + entry.key);
+                Log.d(TAG, "Keeping notification because it's showing guts. " + entry.getKey());
             }
         } else {
-            if (mKeyToRemoveOnGutsClosed != null && mKeyToRemoveOnGutsClosed.equals(entry.key)) {
+            if (mKeyToRemoveOnGutsClosed != null
+                    && mKeyToRemoveOnGutsClosed.equals(entry.getKey())) {
                 mKeyToRemoveOnGutsClosed = null;
                 if (Log.isLoggable(TAG, Log.DEBUG)) {
-                    Log.d(TAG, "Notification that was kept for guts was updated. " + entry.key);
+                    Log.d(TAG, "Notification that was kept for guts was updated. "
+                            + entry.getKey());
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 1116106..5d5c09e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -175,7 +175,7 @@
         mActions = mView.findViewById(com.android.internal.R.id.media_actions);
         mIsViewVisible = mView.isShown();
 
-        final MediaSession.Token token = mRow.getEntry().notification.getNotification().extras
+        final MediaSession.Token token = mRow.getEntry().getSbn().getNotification().extras
                 .getParcelable(Notification.EXTRA_MEDIA_SESSION);
 
         boolean showCompactSeekbar = mMediaManager.getShowCompactMediaSeekbar();
@@ -404,7 +404,7 @@
      * @return new LogMaker
      */
     private LogMaker newLog(int event) {
-        String packageName = mRow.getEntry().notification.getPackageName();
+        String packageName = mRow.getEntry().getSbn().getPackageName();
 
         return new LogMaker(MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR)
                 .setType(event)
@@ -416,7 +416,7 @@
      * @return new LogMaker
      */
     private LogMaker newLog(int event, int subtype) {
-        String packageName = mRow.getEntry().notification.getPackageName();
+        String packageName = mRow.getEntry().getSbn().getPackageName();
         return new LogMaker(MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR)
                 .setType(event)
                 .setSubtype(subtype)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 3950003..c2eff8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -63,7 +63,7 @@
                 return new NotificationMessagingTemplateViewWrapper(ctx, v, row);
             }
             Class<? extends Notification.Style> style =
-                    row.getEntry().notification.getNotification().getNotificationStyle();
+                    row.getEntry().getSbn().getNotification().getNotificationStyle();
             if (Notification.DecoratedCustomViewStyle.class.equals(style)) {
                 return new NotificationDecoratedCustomViewWrapper(ctx, v, row);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index f3d068a..ecab188 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -22,7 +22,6 @@
 import android.util.MathUtils;
 import android.view.View;
 
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarState;
@@ -410,7 +409,7 @@
         if (!mPulsing || mHeadUpManager == null) {
             return false;
         }
-        return mHeadUpManager.isAlerting(entry.key);
+        return mHeadUpManager.isAlerting(entry.getKey());
     }
 
     public boolean isPanelTracking() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
index d0444ae..6ed4a57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
@@ -284,12 +284,12 @@
             ActivatableNotificationView first = s.getFirstVisibleChild();
             String fs = first == null ? "(null)"
                     :  (first instanceof ExpandableNotificationRow)
-                            ? ((ExpandableNotificationRow) first).getEntry().key
+                            ? ((ExpandableNotificationRow) first).getEntry().getKey()
                             : Integer.toHexString(System.identityHashCode(first));
             ActivatableNotificationView last = s.getLastVisibleChild();
             String ls = last == null ? "(null)"
                     :  (last instanceof ExpandableNotificationRow)
-                            ? ((ExpandableNotificationRow) last).getEntry().key
+                            ? ((ExpandableNotificationRow) last).getEntry().getKey()
                             : Integer.toHexString(System.identityHashCode(last));
             android.util.Log.d(TAG, "updateSections: f=" + fs + " s=" + i);
             android.util.Log.d(TAG, "updateSections: l=" + ls + " s=" + i);
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 9817825..5a1a217 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
@@ -602,7 +602,7 @@
         mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
             @Override
             public void onPostEntryUpdated(NotificationEntry entry) {
-                if (!entry.notification.isClearable()) {
+                if (!entry.getSbn().isClearable()) {
                     // The user may have performed a dismiss action on the notification, since it's
                     // not clearable we should snap it back.
                     snapViewIfNeeded(entry);
@@ -1627,7 +1627,7 @@
                     if (!mIsExpanded && row.isHeadsUp() && row.isPinned()
                             && mHeadsUpManager.getTopEntry().getRow() != row
                             && mGroupManager.getGroupSummary(
-                                mHeadsUpManager.getTopEntry().notification)
+                            mHeadsUpManager.getTopEntry().getSbn())
                             != entry) {
                         continue;
                     }
@@ -5525,12 +5525,12 @@
                         // TODO: This is a listener method; we shouldn't be calling it. Can we just
                         // call performRemoveNotification as below?
                         mEntryManager.removeNotification(
-                                rowToRemove.getEntry().key,
+                                rowToRemove.getEntry().getKey(),
                                 null /* ranking */,
                                 NotificationListenerService.REASON_CANCEL_ALL);
                     } else {
                         mEntryManager.performRemoveNotification(
-                                rowToRemove.getEntry().notification,
+                                rowToRemove.getEntry().getSbn(),
                                 NotificationListenerService.REASON_CANCEL_ALL);
                     }
                 } else {
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 7cbdfb0..548afd5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -128,6 +128,7 @@
     private final KeyguardBypassController mKeyguardBypassController;
     private PowerManager.WakeLock mWakeLock;
     private final KeyguardUpdateMonitor mUpdateMonitor;
+    private final DozeParameters mDozeParameters;
     private final KeyguardStateController mKeyguardStateController;
     private final StatusBarWindowController mStatusBarWindowController;
     private final Context mContext;
@@ -146,31 +147,33 @@
 
     private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
 
-    public BiometricUnlockController(Context context,
+    public BiometricUnlockController(
+            Context context,
             DozeScrimController dozeScrimController,
             KeyguardViewMediator keyguardViewMediator,
             ScrimController scrimController,
             StatusBar statusBar,
             KeyguardStateController keyguardStateController, Handler handler,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
-            KeyguardBypassController keyguardBypassController) {
+            KeyguardBypassController keyguardBypassController,
+            DozeParameters dozeParameters) {
         this(context, dozeScrimController, keyguardViewMediator, scrimController, statusBar,
                 keyguardStateController, handler, keyguardUpdateMonitor,
                 context.getResources()
                         .getInteger(com.android.internal.R.integer.config_wakeUpDelayDoze),
-                keyguardBypassController);
+                keyguardBypassController, dozeParameters);
     }
 
     @VisibleForTesting
-    protected BiometricUnlockController(Context context,
-            DozeScrimController dozeScrimController, KeyguardViewMediator keyguardViewMediator,
-            ScrimController scrimController, StatusBar statusBar,
-            KeyguardStateController keyguardStateController, Handler handler,
+    protected BiometricUnlockController(Context context, DozeScrimController dozeScrimController,
+            KeyguardViewMediator keyguardViewMediator, ScrimController scrimController,
+            StatusBar statusBar, KeyguardStateController keyguardStateController, Handler handler,
             KeyguardUpdateMonitor keyguardUpdateMonitor, int wakeUpDelay,
-            KeyguardBypassController keyguardBypassController) {
+            KeyguardBypassController keyguardBypassController, DozeParameters dozeParameters) {
         mContext = context;
         mPowerManager = context.getSystemService(PowerManager.class);
         mUpdateMonitor = keyguardUpdateMonitor;
+        mDozeParameters = dozeParameters;
         mUpdateMonitor.registerCallback(this);
         mMediaManager = Dependency.get(NotificationMediaManager.class);
         Dependency.get(WakefulnessLifecycle.class).addObserver(mWakefulnessObserver);
@@ -284,7 +287,7 @@
         }
         // During wake and unlock, we need to draw black before waking up to avoid abrupt
         // brightness changes due to display state transitions.
-        boolean alwaysOnEnabled = DozeParameters.getInstance(mContext).getAlwaysOn();
+        boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
         boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled && mWakeUpDelay > 0;
         Runnable wakeUp = ()-> {
             if (!wasDeviceInteractive) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
index 0d62703..78ea5c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
@@ -100,6 +100,7 @@
                                     event.getY() - mActivationY);
                         }
                         if (withinDoubleTapSlop) {
+                            makeInactive();
                             if (!mDoubleTapListener.onDoubleTap()) {
                                 return false;
                             }
@@ -134,6 +135,7 @@
         if (mActivated) {
             mActivated = false;
             mActivationListener.onActiveChanged(false);
+            mView.removeCallbacks(mTapTimeoutRunnable);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index bb6a38e..28dac87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.content.Context;
+import android.content.res.Resources;
 import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.PowerManager;
 import android.os.SystemProperties;
@@ -25,7 +25,7 @@
 import android.util.MathUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
+import com.android.systemui.DependencyProvider;
 import com.android.systemui.R;
 import com.android.systemui.doze.AlwaysOnDisplayPolicy;
 import com.android.systemui.doze.DozeScreenState;
@@ -33,9 +33,13 @@
 
 import java.io.PrintWriter;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Retrieve doze information
  */
+@Singleton
 public class DozeParameters implements TunerService.Tunable,
         com.android.systemui.plugins.statusbar.DozeParameters {
     private static final int MAX_DURATION = 60 * 1000;
@@ -44,35 +48,33 @@
     public static final boolean FORCE_BLANKING =
             SystemProperties.getBoolean("debug.force_blanking", false);
 
-    private static DozeParameters sInstance;
-
-    private final Context mContext;
     private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
     private final PowerManager mPowerManager;
 
     private final AlwaysOnDisplayPolicy mAlwaysOnPolicy;
+    private final Resources mResources;
 
     private boolean mDozeAlwaysOn;
     private boolean mControlScreenOffAnimation;
 
-    public static DozeParameters getInstance(Context context) {
-        if (sInstance == null) {
-            sInstance = new DozeParameters(context);
-        }
-        return sInstance;
-    }
-
-    @VisibleForTesting
-    protected DozeParameters(Context context) {
-        mContext = context.getApplicationContext();
-        mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
-        mAlwaysOnPolicy = new AlwaysOnDisplayPolicy(mContext);
+    @Inject
+    protected DozeParameters(
+            @DependencyProvider.MainResources Resources resources,
+            AmbientDisplayConfiguration ambientDisplayConfiguration,
+            AlwaysOnDisplayPolicy alwaysOnDisplayPolicy,
+            PowerManager powerManager,
+            TunerService tunerService) {
+        mResources = resources;
+        mAmbientDisplayConfiguration = ambientDisplayConfiguration;
+        mAlwaysOnPolicy = alwaysOnDisplayPolicy;
 
         mControlScreenOffAnimation = !getDisplayNeedsBlanking();
-        mPowerManager = mContext.getSystemService(PowerManager.class);
+        mPowerManager = powerManager;
         mPowerManager.setDozeAfterScreenOff(!mControlScreenOffAnimation);
 
-        Dependency.get(TunerService.class).addTunable(this, Settings.Secure.DOZE_ALWAYS_ON,
+        tunerService.addTunable(
+                this,
+                Settings.Secure.DOZE_ALWAYS_ON,
                 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
     }
 
@@ -95,7 +97,7 @@
     }
 
     public boolean getDozeSuspendDisplayStateSupported() {
-        return mContext.getResources().getBoolean(R.bool.doze_suspend_display_state_supported);
+        return mResources.getBoolean(R.bool.doze_suspend_display_state_supported);
     }
 
     public int getPulseDuration() {
@@ -103,7 +105,7 @@
     }
 
     public float getScreenBrightnessDoze() {
-        return mContext.getResources().getInteger(
+        return mResources.getInteger(
                 com.android.internal.R.integer.config_screenBrightnessDoze) / 255f;
     }
 
@@ -173,7 +175,7 @@
      * @return {@code true} if screen needs to be completely black before a power transition.
      */
     public boolean getDisplayNeedsBlanking() {
-        return FORCE_BLANKING || !FORCE_NO_BLANKING && mContext.getResources().getBoolean(
+        return FORCE_BLANKING || !FORCE_NO_BLANKING && mResources.getBoolean(
                 com.android.internal.R.bool.config_displayBlanksAfterDoze);
     }
 
@@ -195,24 +197,20 @@
     }
 
     private boolean getBoolean(String propName, int resId) {
-        return SystemProperties.getBoolean(propName, mContext.getResources().getBoolean(resId));
+        return SystemProperties.getBoolean(propName, mResources.getBoolean(resId));
     }
 
     private int getInt(String propName, int resId) {
-        int value = SystemProperties.getInt(propName, mContext.getResources().getInteger(resId));
+        int value = SystemProperties.getInt(propName, mResources.getInteger(resId));
         return MathUtils.constrain(value, 0, MAX_DURATION);
     }
 
-    private String getString(String propName, int resId) {
-        return SystemProperties.get(propName, mContext.getString(resId));
-    }
-
     public int getPulseVisibleDurationExtended() {
         return 2 * getPulseVisibleDuration();
     }
 
     public boolean doubleTapReportsTouchCoordinates() {
-        return mContext.getResources().getBoolean(R.bool.doze_double_tap_reports_touch_coordinates);
+        return mResources.getBoolean(R.bool.doze_double_tap_reports_touch_coordinates);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index ca7c227..442c089 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -276,7 +276,7 @@
                             | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
                     PixelFormat.TRANSLUCENT);
             mEdgePanelLp.privateFlags |=
-                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+                    WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
             mEdgePanelLp.setTitle(TAG + mDisplayId);
             mEdgePanelLp.accessibilityTitle = mContext.getString(R.string.nav_bar_edge_panel);
             mEdgePanelLp.windowAnimations = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
index deb314b..a784984 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
@@ -82,7 +82,7 @@
         final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(mDiameter, mDiameter,
                 mMargin, mMargin, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, flags,
                 PixelFormat.TRANSLUCENT);
-        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+        lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         lp.setTitle("FloatingRotationButton");
         switch (mWindowManager.getDefaultDisplay().getRotation()) {
             case Surface.ROTATION_0:
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 c6d051d..4e06c84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -197,9 +197,9 @@
             mReleaseOnExpandFinish = false;
         } else {
             for (NotificationEntry entry : mEntriesToRemoveAfterExpand) {
-                if (isAlerting(entry.key)) {
+                if (isAlerting(entry.getKey())) {
                     // Maybe the heads-up was removed already
-                    removeAlertEntry(entry.key);
+                    removeAlertEntry(entry.getKey());
                 }
             }
         }
@@ -291,7 +291,7 @@
      */
     public void setRemoteInputActive(
             @NonNull NotificationEntry entry, boolean remoteInputActive) {
-        HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(entry.key);
+        HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(entry.getKey());
         if (headsUpEntry != null && headsUpEntry.remoteInputActive != remoteInputActive) {
             headsUpEntry.remoteInputActive = remoteInputActive;
             if (remoteInputActive) {
@@ -307,7 +307,7 @@
      * area if it's pinned until it's hidden again.
      */
     public void setMenuShown(@NonNull NotificationEntry entry, boolean menuShown) {
-        HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.key);
+        HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.getKey());
         if (headsUpEntry instanceof HeadsUpEntryPhone && entry.isRowPinned()) {
             ((HeadsUpEntryPhone) headsUpEntry).setMenuShownPinned(menuShown);
         }
@@ -375,7 +375,7 @@
         } else {
             if (topEntry.isChildInGroup()) {
                 final NotificationEntry groupSummary =
-                        mGroupManager.getGroupSummary(topEntry.notification);
+                        mGroupManager.getGroupSummary(topEntry.getSbn());
                 if (groupSummary != null) {
                     topEntry = groupSummary;
                 }
@@ -429,9 +429,9 @@
     public void onReorderingAllowed() {
         mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false);
         for (NotificationEntry entry : mEntriesToRemoveWhenReorderingAllowed) {
-            if (isAlerting(entry.key)) {
+            if (isAlerting(entry.getKey())) {
                 // Maybe the heads-up was removed already
-                removeAlertEntry(entry.key);
+                removeAlertEntry(entry.getKey());
             }
         }
         mEntriesToRemoveWhenReorderingAllowed.clear();
@@ -448,7 +448,7 @@
 
     @Override
     protected void onAlertEntryRemoved(AlertEntry alertEntry) {
-        mKeysToRemoveWhenLeavingKeyguard.remove(alertEntry.mEntry.key);
+        mKeysToRemoveWhenLeavingKeyguard.remove(alertEntry.mEntry.getKey());
         super.onAlertEntryRemoved(alertEntry);
         mEntryPool.release((HeadsUpEntryPhone) alertEntry);
     }
@@ -533,9 +533,9 @@
                 } else if (mTrackingHeadsUp) {
                     mEntriesToRemoveAfterExpand.add(entry);
                 } else if (mIsAutoHeadsUp && mStatusBarState == StatusBarState.KEYGUARD) {
-                    mKeysToRemoveWhenLeavingKeyguard.add(entry.key);
+                    mKeysToRemoveWhenLeavingKeyguard.add(entry.getKey());
                 } else {
-                    removeAlertEntry(entry.key);
+                    removeAlertEntry(entry.getKey());
                 }
             };
 
@@ -553,7 +553,7 @@
             if (mEntriesToRemoveWhenReorderingAllowed.contains(mEntry)) {
                 mEntriesToRemoveWhenReorderingAllowed.remove(mEntry);
             }
-            mKeysToRemoveWhenLeavingKeyguard.remove(mEntry.key);
+            mKeysToRemoveWhenLeavingKeyguard.remove(mEntry.getKey());
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 9804f9f..ae18833 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -1212,8 +1212,11 @@
         setClipChildren(shouldClip);
         setClipToPadding(shouldClip);
 
-        AssistHandleViewController controller = Dependency.get(NavigationBarController.class)
-                .getAssistHandlerViewController();
+        NavigationBarController navigationBarController =
+                Dependency.get(NavigationBarController.class);
+        AssistHandleViewController controller =
+                navigationBarController == null
+                        ? null : navigationBarController.getAssistHandlerViewController();
         if (controller != null) {
             controller.setBottomOffset(insets.getSystemWindowInsetBottom());
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index 4d69f77e..2798285 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -105,7 +105,7 @@
      * @return true if the entry was transferred to and should inflate + alert
      */
     public boolean isAlertTransferPending(@NonNull NotificationEntry entry) {
-        PendingAlertInfo alertInfo = mPendingAlerts.get(entry.key);
+        PendingAlertInfo alertInfo = mPendingAlerts.get(entry.getKey());
         return alertInfo != null && alertInfo.isStillValid();
     }
 
@@ -141,7 +141,7 @@
         @Override
         public void onGroupSuppressionChanged(NotificationGroup group, boolean suppressed) {
             if (suppressed) {
-                if (mHeadsUpManager.isAlerting(group.summary.key)) {
+                if (mHeadsUpManager.isAlerting(group.summary.getKey())) {
                     handleSuppressedSummaryAlerted(group.summary, mHeadsUpManager);
                 }
             } else {
@@ -151,11 +151,11 @@
                     return;
                 }
                 GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(mGroupManager.getGroupKey(
-                        group.summary.notification));
+                        group.summary.getSbn()));
                 // Group is no longer suppressed. We should check if we need to transfer the alert
                 // back to the summary now that it's no longer suppressed.
                 if (groupAlertEntry.mAlertSummaryOnNextAddition) {
-                    if (!mHeadsUpManager.isAlerting(group.summary.key)) {
+                    if (!mHeadsUpManager.isAlerting(group.summary.getKey())) {
                         alertNotificationWhenPossible(group.summary, mHeadsUpManager);
                     }
                     groupAlertEntry.mAlertSummaryOnNextAddition = false;
@@ -173,7 +173,7 @@
 
     private void onAlertStateChanged(NotificationEntry entry, boolean isAlerting,
             AlertingNotificationManager alertManager) {
-        if (isAlerting && mGroupManager.isSummaryOfSuppressedGroup(entry.notification)) {
+        if (isAlerting && mGroupManager.isSummaryOfSuppressedGroup(entry.getSbn())) {
             handleSuppressedSummaryAlerted(entry, alertManager);
         }
     }
@@ -184,7 +184,7 @@
         // see as early as we can if we need to abort a transfer.
         @Override
         public void onPendingEntryAdded(NotificationEntry entry) {
-            String groupKey = mGroupManager.getGroupKey(entry.notification);
+            String groupKey = mGroupManager.getGroupKey(entry.getSbn());
             GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(groupKey);
             if (groupAlertEntry != null) {
                 checkShouldTransferBack(groupAlertEntry);
@@ -195,7 +195,7 @@
         // then show the alert.
         @Override
         public void onEntryReinflated(NotificationEntry entry) {
-            PendingAlertInfo alertInfo = mPendingAlerts.remove(entry.key);
+            PendingAlertInfo alertInfo = mPendingAlerts.remove(entry.getKey());
             if (alertInfo != null) {
                 if (alertInfo.isStillValid()) {
                     alertNotificationWhenPossible(entry, mHeadsUpManager);
@@ -214,7 +214,7 @@
             // Removes any alerts pending on this entry. Note that this will not stop any inflation
             // tasks started by a transfer, so this should only be used as clean-up for when
             // inflation is stopped and the pending alert no longer needs to happen.
-            mPendingAlerts.remove(entry.key);
+            mPendingAlerts.remove(entry.getKey());
         }
     };
 
@@ -267,10 +267,10 @@
      */
     private boolean isPendingNotificationInGroup(@NonNull NotificationEntry entry,
             @NonNull NotificationGroup group) {
-        String groupKey = mGroupManager.getGroupKey(group.summary.notification);
-        return mGroupManager.isGroupChild(entry.notification)
-                && Objects.equals(mGroupManager.getGroupKey(entry.notification), groupKey)
-                && !group.children.containsKey(entry.key);
+        String groupKey = mGroupManager.getGroupKey(group.summary.getSbn());
+        return mGroupManager.isGroupChild(entry.getSbn())
+                && Objects.equals(mGroupManager.getGroupKey(entry.getSbn()), groupKey)
+                && !group.children.containsKey(entry.getKey());
     }
 
     /**
@@ -284,10 +284,10 @@
      */
     private void handleSuppressedSummaryAlerted(@NonNull NotificationEntry summary,
             @NonNull AlertingNotificationManager alertManager) {
-        StatusBarNotification sbn = summary.notification;
+        StatusBarNotification sbn = summary.getSbn();
         GroupAlertEntry groupAlertEntry =
                 mGroupAlertEntries.get(mGroupManager.getGroupKey(sbn));
-        if (!mGroupManager.isSummaryOfSuppressedGroup(summary.notification)
+        if (!mGroupManager.isSummaryOfSuppressedGroup(summary.getSbn())
                 || !alertManager.isAlerting(sbn.getKey())
                 || groupAlertEntry == null) {
             return;
@@ -298,7 +298,8 @@
             return;
         }
 
-        NotificationEntry child = mGroupManager.getLogicalChildren(summary.notification).iterator().next();
+        NotificationEntry child =
+                mGroupManager.getLogicalChildren(summary.getSbn()).iterator().next();
         if (child != null) {
             if (child.getRow().keepInParent()
                     || child.isRowRemoved()
@@ -306,7 +307,7 @@
                 // The notification is actually already removed. No need to alert it.
                 return;
             }
-            if (!alertManager.isAlerting(child.key) && onlySummaryAlerts(summary)) {
+            if (!alertManager.isAlerting(child.getKey()) && onlySummaryAlerts(summary)) {
                 groupAlertEntry.mLastAlertTransferTime = SystemClock.elapsedRealtime();
             }
             transferAlertState(summary, child, alertManager);
@@ -324,7 +325,7 @@
      */
     private void transferAlertState(@NonNull NotificationEntry fromEntry, @NonNull NotificationEntry toEntry,
             @NonNull AlertingNotificationManager alertManager) {
-        alertManager.removeNotification(fromEntry.key, true /* releaseImmediately */);
+        alertManager.removeNotification(fromEntry.getKey(), true /* releaseImmediately */);
         alertNotificationWhenPossible(toEntry, alertManager);
     }
 
@@ -347,7 +348,8 @@
             if (!onlySummaryAlerts(summary)) {
                 return;
             }
-            ArrayList<NotificationEntry> children = mGroupManager.getLogicalChildren(summary.notification);
+            ArrayList<NotificationEntry> children = mGroupManager.getLogicalChildren(
+                    summary.getSbn());
             int numChildren = children.size();
             int numPendingChildren = getPendingChildrenNotAlerting(groupAlertEntry.mGroup);
             numChildren += numPendingChildren;
@@ -357,17 +359,18 @@
             boolean releasedChild = false;
             for (int i = 0; i < children.size(); i++) {
                 NotificationEntry entry = children.get(i);
-                if (onlySummaryAlerts(entry) && mHeadsUpManager.isAlerting(entry.key)) {
+                if (onlySummaryAlerts(entry) && mHeadsUpManager.isAlerting(entry.getKey())) {
                     releasedChild = true;
-                    mHeadsUpManager.removeNotification(entry.key, true /* releaseImmediately */);
+                    mHeadsUpManager.removeNotification(
+                            entry.getKey(), true /* releaseImmediately */);
                 }
-                if (mPendingAlerts.containsKey(entry.key)) {
+                if (mPendingAlerts.containsKey(entry.getKey())) {
                     // This is the child that would've been removed if it was inflated.
                     releasedChild = true;
-                    mPendingAlerts.get(entry.key).mAbortOnInflation = true;
+                    mPendingAlerts.get(entry.getKey()).mAbortOnInflation = true;
                 }
             }
-            if (releasedChild && !mHeadsUpManager.isAlerting(summary.key)) {
+            if (releasedChild && !mHeadsUpManager.isAlerting(summary.getKey())) {
                 boolean notifyImmediately = (numChildren - numPendingChildren) > 1;
                 if (notifyImmediately) {
                     alertNotificationWhenPossible(summary, mHeadsUpManager);
@@ -391,20 +394,20 @@
             @NonNull AlertingNotificationManager alertManager) {
         @InflationFlag int contentFlag = alertManager.getContentFlag();
         if (!entry.getRow().isInflationFlagSet(contentFlag)) {
-            mPendingAlerts.put(entry.key, new PendingAlertInfo(entry));
+            mPendingAlerts.put(entry.getKey(), new PendingAlertInfo(entry));
             entry.getRow().updateInflationFlag(contentFlag, true /* shouldInflate */);
             entry.getRow().inflateViews();
             return;
         }
-        if (alertManager.isAlerting(entry.key)) {
-            alertManager.updateNotification(entry.key, true /* alert */);
+        if (alertManager.isAlerting(entry.getKey())) {
+            alertManager.updateNotification(entry.getKey(), true /* alert */);
         } else {
             alertManager.showNotification(entry);
         }
     }
 
     private boolean onlySummaryAlerts(NotificationEntry entry) {
-        return entry.notification.getNotification().getGroupAlertBehavior()
+        return entry.getSbn().getNotification().getGroupAlertBehavior()
                 == Notification.GROUP_ALERT_SUMMARY;
     }
 
@@ -431,7 +434,7 @@
         boolean mAbortOnInflation;
 
         PendingAlertInfo(NotificationEntry entry) {
-            mOriginalNotification = entry.notification;
+            mOriginalNotification = entry.getSbn();
             mEntry = entry;
         }
 
@@ -445,11 +448,11 @@
                 // Notification is aborted due to the transfer being explicitly cancelled
                 return false;
             }
-            if (mEntry.notification.getGroupKey() != mOriginalNotification.getGroupKey()) {
+            if (mEntry.getSbn().getGroupKey() != mOriginalNotification.getGroupKey()) {
                 // Groups have changed
                 return false;
             }
-            if (mEntry.notification.getNotification().isGroupSummary()
+            if (mEntry.getSbn().getNotification().isGroupSummary()
                     != mOriginalNotification.getNotification().isGroupSummary()) {
                 // Notification has changed from group summary to not or vice versa
                 return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index adaea93..e11fc1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -103,8 +103,8 @@
     }
 
     public void onEntryRemoved(NotificationEntry removed) {
-        onEntryRemovedInternal(removed, removed.notification);
-        mIsolatedEntries.remove(removed.key);
+        onEntryRemovedInternal(removed, removed.getSbn());
+        mIsolatedEntries.remove(removed.getKey());
     }
 
     /**
@@ -126,7 +126,7 @@
             return;
         }
         if (isGroupChild(sbn)) {
-            group.children.remove(removed.key);
+            group.children.remove(removed.getKey());
         } else {
             group.summary = null;
         }
@@ -145,7 +145,7 @@
         if (added.isRowRemoved()) {
             added.setDebugThrowable(new Throwable());
         }
-        final StatusBarNotification sbn = added.notification;
+        final StatusBarNotification sbn = added.getSbn();
         boolean isGroupChild = isGroupChild(sbn);
         String groupKey = getGroupKey(sbn);
         NotificationGroup group = mGroupMap.get(groupKey);
@@ -157,17 +157,17 @@
             }
         }
         if (isGroupChild) {
-            NotificationEntry existing = group.children.get(added.key);
+            NotificationEntry existing = group.children.get(added.getKey());
             if (existing != null && existing != added) {
                 Throwable existingThrowable = existing.getDebugThrowable();
-                Log.wtf(TAG, "Inconsistent entries found with the same key " + added.key
+                Log.wtf(TAG, "Inconsistent entries found with the same key " + added.getKey()
                         + "existing removed: " + existing.isRowRemoved()
                         + (existingThrowable != null
                                 ? Log.getStackTraceString(existingThrowable) + "\n": "")
                         + " added removed" + added.isRowRemoved()
                         , new Throwable());
             }
-            group.children.put(added.key, added);
+            group.children.put(added.getKey(), added);
             updateSuppression(group);
         } else {
             group.summary = added;
@@ -210,7 +210,7 @@
         group.suppressed = group.summary != null && !group.expanded
                 && (childCount == 1
                 || (childCount == 0
-                        && group.summary.notification.getNotification().isGroupSummary()
+                        && group.summary.getSbn().getNotification().isGroupSummary()
                         && (hasIsolatedChildren(group) || hasBubbles)));
         if (prevSuppressed != group.suppressed) {
             for (OnGroupChangeListener listener : mListeners) {
@@ -223,7 +223,7 @@
     }
 
     private boolean hasIsolatedChildren(NotificationGroup group) {
-        return getNumberOfIsolatedChildren(group.summary.notification.getGroupKey()) != 0;
+        return getNumberOfIsolatedChildren(group.summary.getSbn().getGroupKey()) != 0;
     }
 
     private int getNumberOfIsolatedChildren(String groupKey) {
@@ -248,18 +248,18 @@
     public void onEntryUpdated(NotificationEntry entry,
             StatusBarNotification oldNotification) {
         String oldKey = oldNotification.getGroupKey();
-        String newKey = entry.notification.getGroupKey();
+        String newKey = entry.getSbn().getGroupKey();
         boolean groupKeysChanged = !oldKey.equals(newKey);
         boolean wasGroupChild = isGroupChild(oldNotification);
-        boolean isGroupChild = isGroupChild(entry.notification);
+        boolean isGroupChild = isGroupChild(entry.getSbn());
         mIsUpdatingUnchangedGroup = !groupKeysChanged && wasGroupChild == isGroupChild;
         if (mGroupMap.get(getGroupKey(oldNotification)) != null) {
             onEntryRemovedInternal(entry, oldNotification);
         }
         onEntryAdded(entry);
         mIsUpdatingUnchangedGroup = false;
-        if (isIsolated(entry.notification)) {
-            mIsolatedEntries.put(entry.key, entry.notification);
+        if (isIsolated(entry.getSbn())) {
+            mIsolatedEntries.put(entry.getKey(), entry.getSbn());
             if (groupKeysChanged) {
                 updateSuppression(mGroupMap.get(oldKey));
                 updateSuppression(mGroupMap.get(newKey));
@@ -284,7 +284,7 @@
         }
         NotificationEntry logicalGroupSummary = getLogicalGroupSummary(sbn);
         return logicalGroupSummary != null
-                && !logicalGroupSummary.notification.equals(sbn);
+                && !logicalGroupSummary.getSbn().equals(sbn);
     }
 
     private int getTotalNumberOfChildren(StatusBarNotification sbn) {
@@ -351,7 +351,7 @@
         if (group == null || group.summary == null) {
             return false;
         }
-        return !group.children.isEmpty() && Objects.equals(group.summary.notification, sbn);
+        return !group.children.isEmpty() && Objects.equals(group.summary.getSbn(), sbn);
     }
 
     /**
@@ -404,7 +404,7 @@
      * will update the suppression of that group.
      */
     public void updateSuppression(NotificationEntry entry) {
-        NotificationGroup group = mGroupMap.get(getGroupKey(entry.notification));
+        NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn()));
         if (group != null) {
             updateSuppression(group);
         }
@@ -489,12 +489,12 @@
      */
 
     private boolean shouldIsolate(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
         NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
         if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) {
             return false;
         }
-        if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.key)) {
+        if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.getKey())) {
             return false;
         }
         return (sbn.getNotification().fullScreenIntent != null
@@ -509,10 +509,10 @@
      * @param entry the notification to isolate
      */
     private void isolateNotification(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
 
         // We will be isolated now, so lets update the groups
-        onEntryRemovedInternal(entry, entry.notification);
+        onEntryRemovedInternal(entry, entry.getSbn());
 
         mIsolatedEntries.put(sbn.getKey(), sbn);
 
@@ -521,7 +521,7 @@
         // even before the groupManager knows about the notification at all.
         // When the notification gets added afterwards it is already isolated and therefore
         // it doesn't lead to an update.
-        updateSuppression(mGroupMap.get(entry.notification.getGroupKey()));
+        updateSuppression(mGroupMap.get(entry.getSbn().getGroupKey()));
         for (OnGroupChangeListener listener : mListeners) {
             listener.onGroupsChanged();
         }
@@ -533,10 +533,10 @@
      * @param entry the notification to un-isolate
      */
     private void stopIsolatingNotification(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
         if (mIsolatedEntries.containsKey(sbn.getKey())) {
             // not isolated anymore, we need to update the groups
-            onEntryRemovedInternal(entry, entry.notification);
+            onEntryRemovedInternal(entry, entry.getSbn());
             mIsolatedEntries.remove(sbn.getKey());
             onEntryAdded(entry);
             for (OnGroupChangeListener listener : mListeners) {
@@ -584,13 +584,13 @@
         @Override
         public String toString() {
             String result = "    summary:\n      "
-                    + (summary != null ? summary.notification : "null")
+                    + (summary != null ? summary.getSbn() : "null")
                     + (summary != null && summary.getDebugThrowable() != null
                             ? Log.getStackTraceString(summary.getDebugThrowable())
                             : "");
             result += "\n    children size: " + children.size();
             for (NotificationEntry child : children.values()) {
-                result += "\n      " + child.notification
+                result += "\n      " + child.getSbn()
                 + (child.getDebugThrowable() != null
                         ? Log.getStackTraceString(child.getDebugThrowable())
                         : "");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 1a3560e..1e10b6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -80,11 +80,14 @@
     private boolean mAodIconsVisible;
     private boolean mIsPulsing;
 
-    public NotificationIconAreaController(Context context, StatusBar statusBar,
+    public NotificationIconAreaController(
+            Context context,
+            StatusBar statusBar,
             StatusBarStateController statusBarStateController,
             NotificationWakeUpCoordinator wakeUpCoordinator,
             KeyguardBypassController keyguardBypassController,
-            NotificationMediaManager notificationMediaManager) {
+            NotificationMediaManager notificationMediaManager,
+            DozeParameters dozeParameters) {
         mStatusBar = statusBar;
         mContrastColorUtil = ContrastColorUtil.getInstance(context);
         mContext = context;
@@ -92,7 +95,7 @@
         mStatusBarStateController = statusBarStateController;
         mStatusBarStateController.addCallback(this);
         mMediaManager = notificationMediaManager;
-        mDozeParameters = DozeParameters.getInstance(mContext);
+        mDozeParameters = dozeParameters;
         mWakeUpCoordinator = wakeUpCoordinator;
         wakeUpCoordinator.addListener(this);
         mBypassController = keyguardBypassController;
@@ -244,10 +247,10 @@
         if (hideCenteredIcon && isCenteredNotificationIcon && !entry.isRowHeadsUp()) {
             return false;
         }
-        if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {
+        if (mEntryManager.getNotificationData().isAmbient(entry.getKey()) && !showAmbient) {
             return false;
         }
-        if (hideCurrentMedia && entry.key.equals(mMediaManager.getMediaNotificationKey())) {
+        if (hideCurrentMedia && entry.getKey().equals(mMediaManager.getMediaNotificationKey())) {
             return false;
         }
         if (!entry.isTopLevelChild()) {
@@ -533,8 +536,7 @@
     }
 
     public void appearAodIcons() {
-        DozeParameters dozeParameters = DozeParameters.getInstance(mContext);
-        if (dozeParameters.shouldControlScreenOff()) {
+        if (mDozeParameters.shouldControlScreenOff()) {
             mAodIcons.setTranslationY(-mAodIconAppearTranslation);
             mAodIcons.setAlpha(0);
             animateInAodIconTranslation();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 177294b..89051cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -43,6 +43,7 @@
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.provider.DeviceConfig;
+import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.MathUtils;
@@ -145,6 +146,7 @@
      * Fling until QS is completely hidden.
      */
     public static final int FLING_HIDE = 2;
+    private final DozeParameters mDozeParameters;
 
     private double mQqsSplitFraction;
 
@@ -453,18 +455,15 @@
     @Inject
     public NotificationPanelView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
             InjectionInflationController injectionInflationController,
-            NotificationWakeUpCoordinator coordinator,
-            PulseExpansionHandler pulseExpansionHandler,
+            NotificationWakeUpCoordinator coordinator, PulseExpansionHandler pulseExpansionHandler,
             DynamicPrivacyController dynamicPrivacyController,
-            KeyguardBypassController bypassController,
-            FalsingManager falsingManager,
-            PluginManager pluginManager,
-            ShadeController shadeController,
+            KeyguardBypassController bypassController, FalsingManager falsingManager,
+            PluginManager pluginManager, ShadeController shadeController,
             NotificationLockscreenUserManager notificationLockscreenUserManager,
             NotificationEntryManager notificationEntryManager,
             KeyguardStateController keyguardStateController,
-            StatusBarStateController statusBarStateController,
-            DozeLog dozeLog) {
+            StatusBarStateController statusBarStateController, DozeLog dozeLog,
+            DozeParameters dozeParameters) {
         super(context, attrs, falsingManager, dozeLog, keyguardStateController,
                 (SysuiStatusBarStateController) statusBarStateController);
         setWillNotDraw(!DEBUG);
@@ -479,6 +478,7 @@
         mCommandQueue = getComponent(context, CommandQueue.class);
         mDisplayId = context.getDisplayId();
         mPulseExpansionHandler = pulseExpansionHandler;
+        mDozeParameters = dozeParameters;
         pulseExpansionHandler.setPulseExpandAbortListener(() -> {
             if (mQs != null) {
                 mQs.animateHeaderSlidingOut();
@@ -541,7 +541,10 @@
         mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
         mLastOrientation = getResources().getConfiguration().orientation;
         mPluginFrame = findViewById(R.id.plugin_frame);
-        mNPVPluginManager = new NPVPluginManager(mPluginFrame, mPluginManager);
+        if (Settings.System.getInt(
+                mContext.getContentResolver(), "npv_plugin_flag", 0) == 1) {
+            mNPVPluginManager = new NPVPluginManager(mPluginFrame, mPluginManager);
+        }
 
 
         initBottomArea();
@@ -778,7 +781,7 @@
             mPluginFrame.setLayoutParams(lp);
         }
 
-        mNPVPluginManager.replaceFrameLayout(mPluginFrame);
+        if (mNPVPluginManager != null) mNPVPluginManager.replaceFrameLayout(mPluginFrame);
     }
 
     private void initBottomArea() {
@@ -808,8 +811,10 @@
         int oldMaxHeight = mQsMaxExpansionHeight;
         if (mQs != null) {
             mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight();
-            mNPVPluginManager.setYOffset(mQsMinExpansionHeight);
-            mQsMinExpansionHeight += mNPVPluginManager.getHeight();
+            if (mNPVPluginManager != null) {
+                mNPVPluginManager.setYOffset(mQsMinExpansionHeight);
+                mQsMinExpansionHeight += mNPVPluginManager.getHeight();
+            }
             mQsMaxExpansionHeight = mQs.getDesiredHeight();
             mNotificationStackScroller.setMaxTopPadding(
                     mQsMaxExpansionHeight + mQsNotificationTopPadding);
@@ -1915,9 +1920,11 @@
                 mBarState != StatusBarState.KEYGUARD && (!mQsExpanded
                         || mQsExpansionFromOverscroll));
         updateEmptyShadeView();
-        mNPVPluginManager.changeVisibility((mBarState != StatusBarState.KEYGUARD)
-                ? View.VISIBLE
-                : View.INVISIBLE);
+        if (mNPVPluginManager != null) {
+            mNPVPluginManager.changeVisibility((mBarState != StatusBarState.KEYGUARD)
+                    ? View.VISIBLE
+                    : View.INVISIBLE);
+        }
         mQsNavbarScrim.setVisibility(mBarState == StatusBarState.SHADE && mQsExpanded
                 && !mStackScrollerOverscrolling && mQsScrimEnabled
                 ? View.VISIBLE
@@ -1975,7 +1982,9 @@
         float qsExpansionFraction = getQsExpansionFraction();
         mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
         int heightDiff = mQs.getDesiredHeight() - mQs.getQsMinExpansionHeight();
-        mNPVPluginManager.setExpansion(qsExpansionFraction, getHeaderTranslation(), heightDiff);
+        if (mNPVPluginManager != null) {
+            mNPVPluginManager.setExpansion(qsExpansionFraction, getHeaderTranslation(), heightDiff);
+        }
         mNotificationStackScroller.setQsExpansionFraction(qsExpansionFraction);
     }
 
@@ -2396,7 +2405,7 @@
                 appearAmount = mNotificationStackScroller.calculateAppearFractionBypass();
             }
             startHeight = -mQs.getQsMinExpansionHeight();
-            startHeight -= mNPVPluginManager.getHeight();
+            if (mNPVPluginManager != null) startHeight -= mNPVPluginManager.getHeight();
         }
         float translation = MathUtils.lerp(startHeight, 0,
                 Math.min(1.0f, appearAmount))
@@ -2540,7 +2549,7 @@
         mKeyguardStatusBar.setListening(listening);
         if (mQs == null) return;
         mQs.setListening(listening);
-        mNPVPluginManager.setListening(listening);
+        if (mNPVPluginManager != null) mNPVPluginManager.setListening(listening);
     }
 
     @Override
@@ -3425,9 +3434,8 @@
 
     public void setPulsing(boolean pulsing) {
         mPulsing = pulsing;
-        DozeParameters dozeParameters = DozeParameters.getInstance(mContext);
-        final boolean animatePulse = !dozeParameters.getDisplayNeedsBlanking()
-                && dozeParameters.getAlwaysOn();
+        final boolean animatePulse = !mDozeParameters.getDisplayNeedsBlanking()
+                && mDozeParameters.getAlwaysOn();
         if (animatePulse) {
             mAnimateNextPositionUpdate = true;
         }
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 5ba19cc..e7d896c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -258,7 +258,7 @@
 
         final ScrimState oldState = mState;
         mState = state;
-        Trace.traceCounter(Trace.TRACE_TAG_APP, "scrim_state", mState.getIndex());
+        Trace.traceCounter(Trace.TRACE_TAG_APP, "scrim_state", mState.ordinal());
 
         if (mCallback != null) {
             mCallback.onCancelled();
@@ -519,22 +519,6 @@
     }
 
     /**
-     * Set front scrim to black, cancelling animations, in order to prepare to fade them
-     * away once the display turns on.
-     */
-    public void prepareForGentleWakeUp() {
-        if (mState == ScrimState.AOD && mDozeParameters.getAlwaysOn()) {
-            mInFrontAlpha = 1f;
-            mInFrontTint = Color.BLACK;
-            mBehindTint = Color.BLACK;
-            mAnimateChange = false;
-            updateScrims();
-            mAnimateChange = true;
-            mAnimationDuration = ANIMATION_DURATION_LONG;
-        }
-    }
-
-    /**
      * If the lock screen sensor is active.
      */
     public void setWakeLockScreenSensorActive(boolean active) {
@@ -595,6 +579,8 @@
         setScrimAlpha(mScrimInFront, mInFrontAlpha);
         setScrimAlpha(mScrimBehind, mBehindAlpha);
         setScrimAlpha(mScrimForBubble, mBubbleAlpha);
+        // The animation could have all already finished, let's call onFinished just in case
+        onFinished();
         dispatchScrimsVisible();
     }
 
@@ -693,9 +679,9 @@
 
             @Override
             public void onAnimationEnd(Animator animation) {
+                scrim.setTag(TAG_KEY_ANIM, null);
                 onFinished(lastCallback);
 
-                scrim.setTag(TAG_KEY_ANIM, null);
                 dispatchScrimsVisible();
 
                 if (!mDeferFinishedListener && mOnAnimationFinished != null) {
@@ -759,9 +745,9 @@
     }
 
     private void onFinished(Callback callback) {
-        if (!hasReachedFinalState(mScrimBehind)
-            || !hasReachedFinalState(mScrimInFront)
-            || !hasReachedFinalState(mScrimForBubble)) {
+        if (isAnimating(mScrimBehind)
+            || isAnimating(mScrimInFront)
+            || isAnimating(mScrimForBubble)) {
             if (callback != null && callback != mCallback) {
                 // Since we only notify the callback that we're finished once everything has
                 // finished, we need to make sure that any changing callbacks are also invoked
@@ -794,11 +780,6 @@
         }
     }
 
-    private boolean hasReachedFinalState(ScrimView scrim) {
-        return scrim.getViewAlpha() == getCurrentScrimAlpha(scrim)
-                && scrim.getTint() == getCurrentScrimTint(scrim);
-    }
-
     private boolean isAnimating(View scrim) {
         return scrim.getTag(TAG_KEY_ANIM) != null;
     }
@@ -854,10 +835,7 @@
             } else {
                 // update the alpha directly
                 updateScrimColor(scrim, alpha, getCurrentScrimTint(scrim));
-                onFinished();
             }
-        } else {
-            onFinished();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 7463c7c..e0597159 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -30,12 +30,30 @@
     /**
      * Initial state.
      */
-    UNINITIALIZED(-1),
+    UNINITIALIZED,
+
+    /**
+     * When turned off by sensors (prox, presence.)
+     */
+    OFF {
+        @Override
+        public void prepare(ScrimState previousState) {
+            mFrontTint = Color.BLACK;
+            mBehindTint = previousState.mBehindTint;
+            mBubbleTint = previousState.mBubbleTint;
+
+            mFrontAlpha = 1f;
+            mBehindAlpha = previousState.mBehindAlpha;
+            mBubbleAlpha = previousState.mBubbleAlpha;
+
+            mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG;
+        }
+    },
 
     /**
      * On the lock screen.
      */
-    KEYGUARD(0) {
+    KEYGUARD {
         @Override
         public void prepare(ScrimState previousState) {
             mBlankScreen = false;
@@ -65,7 +83,7 @@
     /**
      * Showing password challenge on the keyguard.
      */
-    BOUNCER(1) {
+    BOUNCER {
         @Override
         public void prepare(ScrimState previousState) {
             mBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
@@ -77,7 +95,7 @@
     /**
      * Showing password challenge on top of a FLAG_SHOW_WHEN_LOCKED activity.
      */
-    BOUNCER_SCRIMMED(2) {
+    BOUNCER_SCRIMMED {
         @Override
         public void prepare(ScrimState previousState) {
             mBehindAlpha = 0;
@@ -89,7 +107,7 @@
     /**
      * Changing screen brightness from quick settings.
      */
-    BRIGHTNESS_MIRROR(3) {
+    BRIGHTNESS_MIRROR {
         @Override
         public void prepare(ScrimState previousState) {
             mBehindAlpha = 0;
@@ -101,7 +119,7 @@
     /**
      * Always on display or screen off.
      */
-    AOD(4) {
+    AOD {
         @Override
         public void prepare(ScrimState previousState) {
             final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
@@ -136,7 +154,7 @@
     /**
      * When phone wakes up because you received a notification.
      */
-    PULSING(5) {
+    PULSING {
         @Override
         public void prepare(ScrimState previousState) {
             mFrontAlpha = mAodFrontScrimAlpha;
@@ -164,7 +182,7 @@
     /**
      * Unlocked on top of an app (launcher or any other activity.)
      */
-    UNLOCKED(6) {
+    UNLOCKED {
         @Override
         public void prepare(ScrimState previousState) {
             // State that UI will sync to.
@@ -201,7 +219,7 @@
     /**
      * Unlocked with a bubble expanded.
      */
-    BUBBLE_EXPANDED(7) {
+    BUBBLE_EXPANDED {
         @Override
         public void prepare(ScrimState previousState) {
             mFrontTint = Color.TRANSPARENT;
@@ -237,17 +255,12 @@
     DozeParameters mDozeParameters;
     boolean mDisplayRequiresBlanking;
     boolean mWallpaperSupportsAmbientMode;
-    int mIndex;
     boolean mHasBackdrop;
     boolean mLaunchingAffordanceWithPreview;
     boolean mWakeLockScreenSensorActive;
     boolean mKeyguardFadingAway;
     long mKeyguardFadingAwayDuration;
 
-    ScrimState(int index) {
-        mIndex = index;
-    }
-
     public void init(ScrimView scrimInFront, ScrimView scrimBehind, ScrimView scrimForBubble,
             DozeParameters dozeParameters) {
         mScrimInFront = scrimInFront;
@@ -262,10 +275,6 @@
     public void prepare(ScrimState previousState) {
     }
 
-    public int getIndex() {
-        return mIndex;
-    }
-
     public float getFrontAlpha() {
         return mFrontAlpha;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 9093687..550c950 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -179,6 +179,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.EmptyShadeView;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.KeyboardShortcuts;
 import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -198,7 +199,7 @@
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotifPipelineInitializer;
+import com.android.systemui.statusbar.notification.NewNotifPipeline;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationClicker;
@@ -246,6 +247,7 @@
 import javax.inject.Named;
 import javax.inject.Singleton;
 
+import dagger.Lazy;
 import dagger.Subcomponent;
 
 @Singleton
@@ -370,6 +372,7 @@
 
     private final Object mQueueLock = new Object();
 
+    private final FeatureFlags mFeatureFlags;
     private final StatusBarIconController mIconController;
     private final DozeLog mDozeLog;
     private final InjectionInflationController mInjectionInflater;
@@ -381,12 +384,13 @@
     private final DynamicPrivacyController mDynamicPrivacyController;
     private final BypassHeadsUpNotifier mBypassHeadsUpNotifier;
     private final boolean mAllowNotificationLongPress;
-    private final NotifPipelineInitializer mNotifPipelineInitializer;
+    private final Lazy<NewNotifPipeline> mNewNotifPipeline;
     private final FalsingManager mFalsingManager;
     private final BroadcastDispatcher mBroadcastDispatcher;
     private final ConfigurationController mConfigurationController;
     private final StatusBarWindowViewController.Builder mStatusBarWindowViewControllerBuilder;
     private final NotifLog mNotifLog;
+    private final DozeParameters mDozeParameters;
 
     // expanded notifications
     protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -497,8 +501,7 @@
             WallpaperInfo info = wallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT);
             final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean(
                     com.android.internal.R.bool.config_dozeSupportsAodWallpaper);
-            final boolean imageWallpaperInAmbient =
-                    !DozeParameters.getInstance(mContext).getDisplayNeedsBlanking();
+            final boolean imageWallpaperInAmbient = !mDozeParameters.getDisplayNeedsBlanking();
             // If WallpaperInfo is null, it must be ImageWallpaper.
             final boolean supportsAmbientMode = deviceSupportsAodWallpaper
                     && ((info == null && imageWallpaperInAmbient)
@@ -621,6 +624,7 @@
     @Inject
     public StatusBar(
             Context context,
+            FeatureFlags featureFlags,
             LightBarController lightBarController,
             AutoHideController autoHideController,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
@@ -635,7 +639,7 @@
             DynamicPrivacyController dynamicPrivacyController,
             BypassHeadsUpNotifier bypassHeadsUpNotifier,
             @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
-            NotifPipelineInitializer notifPipelineInitializer,
+            Lazy<NewNotifPipeline> newNotifPipeline,
             FalsingManager falsingManager,
             BroadcastDispatcher broadcastDispatcher,
             RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
@@ -674,8 +678,10 @@
             ConfigurationController configurationController,
             StatusBarWindowController statusBarWindowController,
             StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
-            NotifLog notifLog) {
+            NotifLog notifLog,
+            DozeParameters dozeParameters) {
         super(context);
+        mFeatureFlags = featureFlags;
         mLightBarController = lightBarController;
         mAutoHideController = autoHideController;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -690,7 +696,7 @@
         mDynamicPrivacyController = dynamicPrivacyController;
         mBypassHeadsUpNotifier = bypassHeadsUpNotifier;
         mAllowNotificationLongPress = allowNotificationLongPress;
-        mNotifPipelineInitializer = notifPipelineInitializer;
+        mNewNotifPipeline = newNotifPipeline;
         mFalsingManager = falsingManager;
         mBroadcastDispatcher = broadcastDispatcher;
         mRemoteInputQuickSettingsDisabler = remoteInputQuickSettingsDisabler;
@@ -730,6 +736,7 @@
         mStatusBarWindowController = statusBarWindowController;
         mStatusBarWindowViewControllerBuilder = statusBarWindowViewControllerBuilder;
         mNotifLog = notifLog;
+        mDozeParameters = dozeParameters;
 
         mBubbleExpandListener =
                 (isExpanding, key) -> {
@@ -750,7 +757,7 @@
         KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance();
         if (sliceProvider != null) {
             sliceProvider.initDependencies(mMediaManager, mStatusBarStateController,
-                    mKeyguardBypassController, DozeParameters.getInstance(mContext));
+                    mKeyguardBypassController, mDozeParameters);
         } else {
             Log.w(TAG, "Cannot init KeyguardSliceProvider dependencies");
         }
@@ -1032,13 +1039,12 @@
                     if (mStatusBarWindow != null) {
                         mStatusBarWindowViewController.onScrimVisibilityChanged(scrimsVisible);
                     }
-                }, DozeParameters.getInstance(mContext),
+                }, mDozeParameters,
                 mContext.getSystemService(AlarmManager.class),
                 mKeyguardStateController);
         mNotificationPanel.initDependencies(this, mGroupManager, mNotificationShelf,
                 mHeadsUpManager, mNotificationIconAreaController, mScrimController);
-        mDozeScrimController = new DozeScrimController(DozeParameters.getInstance(context),
-                mDozeLog);
+        mDozeScrimController = new DozeScrimController(mDozeParameters, mDozeLog);
 
         BackDropView backdrop = mStatusBarWindow.findViewById(R.id.backdrop);
         mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front),
@@ -1210,7 +1216,9 @@
         mGroupAlertTransferHelper.bind(mEntryManager, mGroupManager);
         mNotificationListController.bind();
 
-        mNotifPipelineInitializer.initialize(mNotificationListener);
+        if (mFeatureFlags.isNewNotifPipelineEnabled()) {
+            mNewNotifPipeline.get().initialize(mNotificationListener);
+        }
     }
 
     /**
@@ -1343,7 +1351,7 @@
         mBiometricUnlockController = new BiometricUnlockController(mContext,
                 mDozeScrimController, mKeyguardViewMediator,
                 mScrimController, this, mKeyguardStateController, new Handler(),
-                mKeyguardUpdateMonitor, mKeyguardBypassController);
+                mKeyguardUpdateMonitor, mKeyguardBypassController, mDozeParameters);
         putComponent(BiometricUnlockController.class, mBiometricUnlockController);
         mStatusBarKeyguardViewManager = mKeyguardViewMediator.registerStatusBar(this,
                 getBouncerContainer(), mNotificationPanel, mBiometricUnlockController,
@@ -1887,7 +1895,7 @@
 
     public void maybeEscalateHeadsUp() {
         mHeadsUpManager.getAllEntries().forEach(entry -> {
-            final StatusBarNotification sbn = entry.notification;
+            final StatusBarNotification sbn = entry.getSbn();
             final Notification notification = sbn.getNotification();
             if (notification.fullScreenIntent != null) {
                 if (DEBUG) {
@@ -3571,8 +3579,7 @@
         mDozing = isDozing;
 
         // Collapse the notification panel if open
-        boolean dozingAnimated = mDozingRequested
-                && DozeParameters.getInstance(mContext).shouldControlScreenOff();
+        boolean dozingAnimated = mDozingRequested && mDozeParameters.shouldControlScreenOff();
         mNotificationPanel.resetViews(dozingAnimated);
 
         updateQsExpansionEnabled();
@@ -3689,9 +3696,7 @@
             // Indicate that the group expansion is changing at this time -- this way the group
             // and children backgrounds / divider animations will look correct.
             entry.setGroupExpansionChanging(true);
-            if (entry.notification != null) {
-                userId = entry.notification.getUserId();
-            }
+            userId = entry.getSbn().getUserId();
         }
         boolean fullShadeNeedsBouncer = !mLockscreenUserManager.
                 userAllowsPrivateNotificationsInPublic(mLockscreenUserManager.getCurrentUserId())
@@ -3828,7 +3833,7 @@
      */
     private void updateNotificationPanelTouchState() {
         boolean goingToSleepWithoutAnimation = isGoingToSleep()
-                && !DozeParameters.getInstance(mContext).shouldControlScreenOff();
+                && !mDozeParameters.shouldControlScreenOff();
         boolean disabled = (!mDeviceInteractive && !mPulsing) || goingToSleepWithoutAnimation;
         mNotificationPanel.setTouchAndAnimationDisabled(disabled);
         mNotificationIconAreaController.setAnimationsEnabled(!disabled);
@@ -4018,6 +4023,13 @@
         } else if (isPulsing()) {
             mScrimController.transitionTo(ScrimState.PULSING,
                     mDozeScrimController.getScrimCallback());
+        } else if (mDozeServiceHost.hasPendingScreenOffCallback()) {
+            mScrimController.transitionTo(ScrimState.OFF, new ScrimController.Callback() {
+                @Override
+                public void onFinished() {
+                    mDozeServiceHost.executePendingScreenOffCallback();
+                }
+            });
         } else if (mDozing && !unlocking) {
             mScrimController.transitionTo(ScrimState.AOD);
         } else if (mIsKeyguard && !unlocking) {
@@ -4044,6 +4056,7 @@
         private boolean mAnimateWakeup;
         private boolean mAnimateScreenOff;
         private boolean mIgnoreTouchWhilePulsing;
+        private Runnable mPendingScreenOffCallback;
         @VisibleForTesting
         boolean mWakeLockScreenPerformsAuth = SystemProperties.getBoolean(
                 "persist.sysui.wake_performs_auth", true);
@@ -4266,8 +4279,33 @@
         }
 
         @Override
-        public void prepareForGentleWakeUp() {
-            mScrimController.prepareForGentleWakeUp();
+        public void prepareForGentleSleep(Runnable onDisplayOffCallback) {
+            if (onDisplayOffCallback != null) {
+                Log.w(TAG, "Overlapping onDisplayOffCallback. Ignoring previous one.");
+            }
+            mPendingScreenOffCallback = onDisplayOffCallback;
+            updateScrimController();
+        }
+
+        /**
+         * When the dozing host is waiting for scrims to fade out to change the display state.
+         */
+        boolean hasPendingScreenOffCallback() {
+            return mPendingScreenOffCallback != null;
+        }
+
+        /**
+         * Executes an nullifies the pending display state callback.
+         *
+         * @see #hasPendingScreenOffCallback()
+         * @see #prepareForGentleSleep(Runnable)
+         */
+        void executePendingScreenOffCallback() {
+            if (mPendingScreenOffCallback == null) {
+                return;
+            }
+            mPendingScreenOffCallback.run();
+            mPendingScreenOffCallback = null;
         }
 
         private void dispatchTap(View view, float x, float y) {
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 dfec195..64a45e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -245,7 +245,7 @@
         StatusBarNotification parentToCancel = null;
         if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
             StatusBarNotification summarySbn =
-                    mGroupManager.getLogicalGroupSummary(sbn).notification;
+                    mGroupManager.getLogicalGroupSummary(sbn).getSbn();
             if (shouldAutoCancel(summarySbn)) {
                 parentToCancel = summarySbn;
             }
@@ -310,7 +310,7 @@
         if (!TextUtils.isEmpty(entry.remoteInputText)) {
             remoteInputText = entry.remoteInputText;
         }
-        if (!TextUtils.isEmpty(remoteInputText) && !controller.isSpinning(entry.key)) {
+        if (!TextUtils.isEmpty(remoteInputText) && !controller.isSpinning(entry.getKey())) {
             fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
                     remoteInputText.toString());
         }
@@ -409,11 +409,11 @@
         if (mNotificationInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) {
             if (shouldSuppressFullScreenIntent(entry)) {
                 if (DEBUG) {
-                    Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + entry.key);
+                    Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + entry.getKey());
                 }
             } else if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) {
                 if (DEBUG) {
-                    Log.d(TAG, "No Fullscreen intent: not important enough: " + entry.key);
+                    Log.d(TAG, "No Fullscreen intent: not important enough: " + entry.getKey());
                 }
             } else {
                 // Stop screensaver if the notification has a fullscreen intent.
@@ -432,8 +432,8 @@
                 }
                 try {
                     EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
-                            entry.key);
-                    entry.notification.getNotification().fullScreenIntent.send();
+                            entry.getKey());
+                    entry.getSbn().getNotification().fullScreenIntent.send();
                     entry.notifyFullScreenIntentLaunched();
                     mMetricsLogger.count("note_fullscreen", 1);
                 } catch (PendingIntent.CanceledException e) {
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 f4a26ba..b01a8d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -201,7 +201,7 @@
                         NotificationVisibility visibility,
                         boolean removedByUser) {
                     StatusBarNotificationPresenter.this.onNotificationRemoved(
-                            entry.key, entry.notification);
+                            entry.getKey(), entry.getSbn());
                     if (removedByUser) {
                         maybeEndAmbientPulse();
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 724b462..ca7a936 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -21,7 +21,6 @@
 import static com.android.systemui.DejankUtils.whitelistIpcs;
 import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
 
-import android.app.ActivityManager;
 import android.app.IActivityManager;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
@@ -39,8 +38,6 @@
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
@@ -94,24 +91,14 @@
     private final ArrayList<WeakReference<StatusBarWindowCallback>>
             mCallbacks = Lists.newArrayList();
 
-    private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+    private final SysuiColorExtractor mColorExtractor;
 
     @Inject
-    public StatusBarWindowController(Context context,
-            StatusBarStateController statusBarStateController,
-            ConfigurationController configurationController,
-            KeyguardBypassController keyguardBypassController) {
-        this(context, context.getSystemService(WindowManager.class), ActivityManager.getService(),
-                DozeParameters.getInstance(context), statusBarStateController,
-                configurationController, keyguardBypassController);
-    }
-
-    @VisibleForTesting
     public StatusBarWindowController(Context context, WindowManager windowManager,
             IActivityManager activityManager, DozeParameters dozeParameters,
             StatusBarStateController statusBarStateController,
             ConfigurationController configurationController,
-            KeyguardBypassController keyguardBypassController) {
+            KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor) {
         mContext = context;
         mWindowManager = windowManager;
         mActivityManager = activityManager;
@@ -120,6 +107,7 @@
         mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
         mLpChanged = new LayoutParams();
         mKeyguardBypassController = keyguardBypassController;
+        mColorExtractor = colorExtractor;
         mLockScreenDisplayTimeout = context.getResources()
                 .getInteger(R.integer.config_lockScreenDisplayTimeout);
         ((SysuiStatusBarStateController) statusBarStateController)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
index 1ce7763..fd3f9c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
@@ -93,7 +93,8 @@
             NotificationEntryManager notificationEntryManager,
             KeyguardStateController keyguardStateController,
             SysuiStatusBarStateController statusBarStateController,
-            DozeLog dozeLog) {
+            DozeLog dozeLog,
+            DozeParameters dozeParameters) {
         mView = view;
         mFalsingManager = falsingManager;
 
@@ -113,7 +114,8 @@
                 notificationEntryManager,
                 keyguardStateController,
                 statusBarStateController,
-                dozeLog);
+                dozeLog,
+                dozeParameters);
         ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
         notificationPanelView.setVisibility(View.INVISIBLE);
@@ -485,6 +487,7 @@
         private final NotificationLockscreenUserManager mNotificationLockScreenUserManager;
         private final NotificationEntryManager mNotificationEntryManager;
         private final DozeLog mDozeLog;
+        private final DozeParameters mDozeParameters;
         private StatusBarWindowView mView;
 
         @Inject
@@ -501,7 +504,8 @@
                 NotificationEntryManager notificationEntryManager,
                 KeyguardStateController keyguardStateController,
                 StatusBarStateController statusBarStateController,
-                DozeLog dozeLog) {
+                DozeLog dozeLog,
+                DozeParameters dozeParameters) {
             mInjectionInflationController = injectionInflationController;
             mCoordinator = coordinator;
             mPulseExpansionHandler = pulseExpansionHandler;
@@ -515,6 +519,7 @@
             mKeyguardStateController = keyguardStateController;
             mStatusBarStateController = (SysuiStatusBarStateController) statusBarStateController;
             mDozeLog = dozeLog;
+            mDozeParameters = dozeParameters;
         }
 
         /**
@@ -552,7 +557,8 @@
                     mNotificationEntryManager,
                     mKeyguardStateController,
                     mStatusBarStateController,
-                    mDozeLog);
+                    mDozeLog,
+                    mDozeParameters);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index ce929b7..44be6bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -93,10 +93,10 @@
     public static void setShowForAllUsers(Dialog dialog, boolean show) {
         if (show) {
             dialog.getWindow().getAttributes().privateFlags |=
-                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+                    WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         } else {
             dialog.getWindow().getAttributes().privateFlags &=
-                    ~WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+                    ~WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         }
     }
 
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 b84dc47..6828c32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -117,7 +117,7 @@
     }
 
     protected boolean hasFullScreenIntent(@NonNull NotificationEntry entry) {
-        return entry.notification.getNotification().fullScreenIntent != null;
+        return entry.getSbn().getNotification().fullScreenIntent != null;
     }
 
     protected void setEntryPinned(
@@ -206,7 +206,7 @@
     public void snooze() {
         for (String key : mAlertEntries.keySet()) {
             AlertEntry entry = getHeadsUpEntry(key);
-            String packageName = entry.mEntry.notification.getPackageName();
+            String packageName = entry.mEntry.getSbn().getPackageName();
             mSnoozedPackages.put(snoozeKey(packageName, mUser),
                     mClock.currentTimeMillis() + mSnoozeLengthMs);
         }
@@ -328,8 +328,8 @@
      * one should be ranked higher and 0 if they are equal.
      */
     public int compare(@NonNull NotificationEntry a, @NonNull NotificationEntry b) {
-        AlertEntry aEntry = getHeadsUpEntry(a.key);
-        AlertEntry bEntry = getHeadsUpEntry(b.key);
+        AlertEntry aEntry = getHeadsUpEntry(a.getKey());
+        AlertEntry bEntry = getHeadsUpEntry(b.getKey());
         if (aEntry == null || bEntry == null) {
             return aEntry == null ? 1 : -1;
         }
@@ -341,7 +341,7 @@
      * until it's collapsed again.
      */
     public void setExpanded(@NonNull NotificationEntry entry, boolean expanded) {
-        HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.key);
+        HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.getKey());
         if (headsUpEntry != null && entry.isRowPinned()) {
             headsUpEntry.setExpanded(expanded);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
index be27741..c6ae669 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
@@ -144,13 +144,13 @@
             return false;
         }
         // If we are showing the spinner we don't want to add the buttons.
-        boolean showingSpinner = entry.notification.getNotification()
+        boolean showingSpinner = entry.getSbn().getNotification()
                 .extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false);
         if (showingSpinner) {
             return false;
         }
         // If we are keeping the notification around while sending we don't want to add the buttons.
-        boolean hideSmartReplies = entry.notification.getNotification()
+        boolean hideSmartReplies = entry.getSbn().getNotification()
                 .extras.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false);
         if (hideSmartReplies) {
             return false;
@@ -168,7 +168,7 @@
     public static SmartRepliesAndActions chooseSmartRepliesAndActions(
             SmartReplyConstants smartReplyConstants,
             final NotificationEntry entry) {
-        Notification notification = entry.notification.getNotification();
+        Notification notification = entry.getSbn().getNotification();
         Pair<RemoteInput, Notification.Action> remoteInputActionPair =
                 notification.findRemoteInputActionPair(false /* freeform */);
         Pair<RemoteInput, Notification.Action> freeformRemoteInputActionPair =
@@ -177,7 +177,7 @@
         if (!smartReplyConstants.isEnabled()) {
             if (DEBUG) {
                 Log.d(TAG, "Smart suggestions not enabled, not adding suggestions for "
-                        + entry.notification.getKey());
+                        + entry.getSbn().getKey());
             }
             return new SmartRepliesAndActions(null, null);
         }
@@ -271,7 +271,7 @@
      * through the remote input.
      */
     public static boolean hasFreeformRemoteInput(NotificationEntry entry) {
-        Notification notification = entry.notification.getNotification();
+        Notification notification = entry.getSbn().getNotification();
         return null != notification.findRemoteInputActionPair(true /* freeform */);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 43795dc..7b4a7d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -23,12 +23,16 @@
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.RemoteInput;
+import android.content.ClipDescription;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.pm.ShortcutManager;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.net.Uri;
 import android.os.Bundle;
+import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.text.Editable;
@@ -53,8 +57,13 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import androidx.core.view.inputmethod.EditorInfoCompat;
+import androidx.core.view.inputmethod.InputConnectionCompat;
+import androidx.core.view.inputmethod.InputContentInfoCompat;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -65,6 +74,7 @@
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.LightBarController;
 
+import java.util.HashMap;
 import java.util.function.Consumer;
 
 /**
@@ -88,6 +98,8 @@
     private RemoteInputController mController;
     private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
 
+    private IStatusBarService mStatusBarManagerService;
+
     private NotificationEntry mEntry;
 
     private boolean mRemoved;
@@ -103,6 +115,8 @@
     public RemoteInputView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mRemoteInputQuickSettingsDisabler = Dependency.get(RemoteInputQuickSettingsDisabler.class);
+        mStatusBarManagerService = IStatusBarService.Stub.asInterface(
+                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
     }
 
     @Override
@@ -128,7 +142,7 @@
 
                 if (isSoftImeEvent || isKeyboardEnterKey) {
                     if (mEditText.length() > 0) {
-                        sendRemoteInput();
+                        sendRemoteInput(prepareRemoteInputFromText());
                     }
                     // Consume action to prevent IME from closing.
                     return true;
@@ -141,7 +155,7 @@
         mEditText.mRemoteInputView = this;
     }
 
-    private void sendRemoteInput() {
+    protected Intent prepareRemoteInputFromText() {
         Bundle results = new Bundle();
         results.putString(mRemoteInput.getResultKey(), mEditText.getText().toString());
         Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -153,12 +167,31 @@
             RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE);
         }
 
+        return fillInIntent;
+    }
+
+    protected Intent prepareRemoteInputFromData(String contentType, Uri data) {
+        HashMap<String, Uri> results = new HashMap<>();
+        results.put(contentType, data);
+        try {
+            mStatusBarManagerService.grantInlineReplyUriPermission(
+                    mEntry.getSbn().getKey(), data);
+        } catch (Exception e) {
+            Log.e(TAG, "Failed to grant URI permissions:" + e.getMessage(), e);
+        }
+        Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        RemoteInput.addDataResultToIntent(mRemoteInput, fillInIntent, results);
+
+        return fillInIntent;
+    }
+
+    private void sendRemoteInput(Intent intent) {
         mEditText.setEnabled(false);
         mSendButton.setVisibility(INVISIBLE);
         mProgressBar.setVisibility(VISIBLE);
         mEntry.remoteInputText = mEditText.getText();
         mEntry.lastRemoteInputSent = SystemClock.elapsedRealtime();
-        mController.addSpinning(mEntry.key, mToken);
+        mController.addSpinning(mEntry.getKey(), mToken);
         mController.removeRemoteInput(mEntry, mToken);
         mEditText.mShowImeOnInputConnection = false;
         mController.remoteInputSent(mEntry);
@@ -170,17 +203,17 @@
         // but that's an edge case, and also because we can't always know which package will receive
         // an intent, so we just reset for the publisher.
         getContext().getSystemService(ShortcutManager.class).onApplicationActive(
-                mEntry.notification.getPackageName(),
-                mEntry.notification.getUser().getIdentifier());
+                mEntry.getSbn().getPackageName(),
+                mEntry.getSbn().getUser().getIdentifier());
 
         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_SEND,
-                mEntry.notification.getPackageName());
+                mEntry.getSbn().getPackageName());
         try {
-            mPendingIntent.send(mContext, 0, fillInIntent);
+            mPendingIntent.send(mContext, 0, intent);
         } catch (PendingIntent.CanceledException e) {
             Log.i(TAG, "Unable to send remote input result", e);
             MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_FAIL,
-                    mEntry.notification.getPackageName());
+                    mEntry.getSbn().getPackageName());
         }
     }
 
@@ -195,7 +228,9 @@
                 LayoutInflater.from(context).inflate(R.layout.remote_input, root, false);
         v.mController = controller;
         v.mEntry = entry;
-        v.mEditText.setTextOperationUser(computeTextOperationUser(entry.notification.getUser()));
+        UserHandle user = computeTextOperationUser(entry.getSbn().getUser());
+        v.mEditText.mUser = user;
+        v.mEditText.setTextOperationUser(user);
         v.setTag(VIEW_TAG);
 
         return v;
@@ -204,7 +239,7 @@
     @Override
     public void onClick(View v) {
         if (v == mSendButton) {
-            sendRemoteInput();
+            sendRemoteInput(prepareRemoteInputFromText());
         }
     }
 
@@ -249,7 +284,7 @@
         mRemoteInputQuickSettingsDisabler.setRemoteInputActive(false);
 
         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_CLOSE,
-                mEntry.notification.getPackageName());
+                mEntry.getSbn().getPackageName());
     }
 
     @Override
@@ -269,7 +304,7 @@
             return;
         }
         mController.removeRemoteInput(mEntry, mToken);
-        mController.removeSpinning(mEntry.key, mToken);
+        mController.removeSpinning(mEntry.getKey(), mToken);
     }
 
     public void setPendingIntent(PendingIntent pendingIntent) {
@@ -314,7 +349,7 @@
 
     public void focus() {
         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_OPEN,
-                mEntry.notification.getPackageName());
+                mEntry.getSbn().getPackageName());
 
         setVisibility(VISIBLE);
         if (mWrapper != null) {
@@ -353,7 +388,7 @@
         mEditText.setEnabled(true);
         mSendButton.setVisibility(VISIBLE);
         mProgressBar.setVisibility(INVISIBLE);
-        mController.removeSpinning(mEntry.key, mToken);
+        mController.removeSpinning(mEntry.getKey(), mToken);
         updateSendButton();
         onDefocus(false /* animate */);
 
@@ -505,7 +540,7 @@
     }
 
     public boolean isSending() {
-        return getVisibility() == VISIBLE && mController.isSpinning(mEntry.key, mToken);
+        return getVisibility() == VISIBLE && mController.isSpinning(mEntry.getKey(), mToken);
     }
 
     /**
@@ -518,6 +553,7 @@
         private RemoteInputView mRemoteInputView;
         boolean mShowImeOnInputConnection;
         private LightBarController mLightBarController;
+        UserHandle mUser;
 
         public RemoteEditText(Context context, AttributeSet attrs) {
             super(context, attrs);
@@ -617,11 +653,47 @@
 
         @Override
         public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+            String[] allowedDataTypes = mRemoteInputView.mRemoteInput.getAllowedDataTypes()
+                    .toArray(new String[0]);
+            EditorInfoCompat.setContentMimeTypes(outAttrs, allowedDataTypes);
             final InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
 
-            if (mShowImeOnInputConnection && inputConnection != null) {
+            final InputConnectionCompat.OnCommitContentListener callback =
+                    new InputConnectionCompat.OnCommitContentListener() {
+                        @Override
+                        public boolean onCommitContent(
+                                InputContentInfoCompat inputContentInfoCompat, int i,
+                                Bundle bundle) {
+                            Uri contentUri = inputContentInfoCompat.getContentUri();
+                            ClipDescription description = inputContentInfoCompat.getDescription();
+                            String mimeType = null;
+                            if (description != null && description.getMimeTypeCount() > 0) {
+                                mimeType = description.getMimeType(0);
+                            }
+                            if (mimeType != null) {
+                                Intent dataIntent = mRemoteInputView.prepareRemoteInputFromData(
+                                        mimeType, contentUri);
+                                mRemoteInputView.sendRemoteInput(dataIntent);
+                            }
+                            return true;
+                        }
+                    };
+
+            InputConnection ic = InputConnectionCompat.createWrapper(
+                    inputConnection, outAttrs, callback);
+
+            Context userContext = null;
+            try {
+                userContext = mContext.createPackageContextAsUser(
+                        mContext.getPackageName(), 0, mUser);
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.e(TAG, "Unable to create user context:" + e.getMessage(), e);
+            }
+
+            if (mShowImeOnInputConnection && ic != null) {
+                Context targetContext = userContext != null ? userContext : getContext();
                 final InputMethodManager imm =
-                        getContext().getSystemService(InputMethodManager.class);
+                        targetContext.getSystemService(InputMethodManager.class);
                 if (imm != null) {
                     // onCreateInputConnection is called by InputMethodManager in the middle of
                     // setting up the connection to the IME; wait with requesting the IME until that
@@ -636,7 +708,7 @@
                 }
             }
 
-            return inputConnection;
+            return ic;
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index b5f660a..65bb28f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -350,7 +350,7 @@
                         () -> {
                             smartReplyController.smartActionClicked(
                                     entry, actionIndex, action, smartActions.fromAssistant);
-                            headsUpManager.removeNotification(entry.key, true);
+                            headsUpManager.removeNotification(entry.getKey(), true);
                         }, entry.getRow());
         if (useDelayedOnClickListener) {
             onClickListener = new DelayedOnClickListener(onClickListener,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 95ae23c..bcfbdac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -314,7 +314,6 @@
         // adb shell settings put system enable_fullscreen_user_switcher 1  # Turn it on.
         // Restart SystemUI or adb reboot.
         final int DEFAULT = -1;
-        // TODO(b/140061064)
         final int overrideUseFullscreenUserSwitcher =
                 whitelistIpcs(() -> Settings.System.getInt(mContext.getContentResolver(),
                         "enable_fullscreen_user_switcher", DEFAULT));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS
new file mode 100644
index 0000000..a601e9b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS
@@ -0,0 +1,8 @@
+# Android TV Core Framework
+rgl@google.com
+valiiftime@google.com
+galinap@google.com
+patrikf@google.com
+robhor@google.com
+sergeynv@google.com
+
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
index 0a3e34e..fd99ef3 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.PermissionChecker;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.hardware.usb.IUsbManager;
@@ -63,6 +64,7 @@
         mDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
         mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
         mResolveInfo = (ResolveInfo) intent.getParcelableExtra("rinfo");
+        String packageName = intent.getStringExtra(UsbManager.EXTRA_PACKAGE);
 
         PackageManager packageManager = getPackageManager();
         String appName = mResolveInfo.loadLabel(packageManager).toString();
@@ -74,8 +76,20 @@
                     mAccessory.getDescription());
             mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory);
         } else {
-            ap.mMessage = getString(R.string.usb_device_confirm_prompt, appName,
-                    mDevice.getProductName());
+            int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+            boolean hasRecordPermission =
+                    PermissionChecker.checkPermissionForPreflight(
+                            this, android.Manifest.permission.RECORD_AUDIO, -1, uid,
+                            packageName)
+                            == android.content.pm.PackageManager.PERMISSION_GRANTED;
+            boolean isAudioCaptureDevice = mDevice.getHasAudioCapture();
+            boolean useRecordWarning = isAudioCaptureDevice && !hasRecordPermission;
+
+            int strID = useRecordWarning
+                    ? R.string.usb_device_confirm_prompt_warn
+                    : R.string.usb_device_confirm_prompt;
+
+            ap.mMessage = getString(strID, appName, mDevice.getProductName());
             mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice);
         }
         ap.mPositiveButtonText = getString(android.R.string.ok);
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
index cce5bca..fdffc43 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.util.sensors;
 
-import android.content.Context;
+import android.content.res.Resources;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
@@ -25,6 +25,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.DependencyProvider;
 import com.android.systemui.R;
 
 import java.util.ArrayList;
@@ -64,9 +65,10 @@
     };
 
     @Inject
-    public ProximitySensor(Context context, AsyncSensorManager sensorManager) {
+    public ProximitySensor(@DependencyProvider.MainResources Resources resources,
+            AsyncSensorManager sensorManager) {
         mSensorManager = sensorManager;
-        Sensor sensor = findBrightnessSensor(context);
+        Sensor sensor = findBrightnessSensor(resources);
 
         if (sensor == null) {
             mUsingBrightnessSensor = false;
@@ -106,8 +108,8 @@
         registerInternal();
     }
 
-    private Sensor findBrightnessSensor(Context context) {
-        String sensorType = context.getString(R.string.doze_brightness_sensor_type);
+    private Sensor findBrightnessSensor(Resources resources) {
+        String sensorType = resources.getString(R.string.doze_brightness_sensor_type);
         List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
         Sensor sensor = null;
         for (Sensor s : sensorList) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index dd5211d..0068113 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -56,8 +56,10 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.colorextraction.ColorExtractor;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationPresenter;
@@ -141,6 +143,10 @@
     private BubbleController.BubbleExpandListener mBubbleExpandListener;
     @Mock
     private PendingIntent mDeleteIntent;
+    @Mock
+    private SysuiColorExtractor mColorExtractor;
+    @Mock
+    ColorExtractor.GradientColors mGradientColors;
 
     private BubbleData mBubbleData;
 
@@ -150,11 +156,12 @@
         mStatusBarView = new FrameLayout(mContext);
         mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
         mContext.addMockSystemService(FaceManager.class, mFaceManager);
+        when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
 
         // Bubbles get added to status bar window view
         mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
                 mActivityManager, mDozeParameters, mStatusBarStateController,
-                mConfigurationController, mKeyguardBypassController);
+                mConfigurationController, mKeyguardBypassController, mColorExtractor);
         mStatusBarWindowController.add(mStatusBarView, 120 /* height */);
 
         // Need notifications for bubbles
@@ -165,8 +172,8 @@
 
         // Return non-null notification data from the NEM
         when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData);
-        when(mNotificationData.get(mRow.getEntry().key)).thenReturn(mRow.getEntry());
-        when(mNotificationData.getChannel(mRow.getEntry().key)).thenReturn(
+        when(mNotificationData.get(mRow.getEntry().getKey())).thenReturn(mRow.getEntry());
+        when(mNotificationData.getChannel(mRow.getEntry().getKey())).thenReturn(
                 mRow.getEntry().getChannel());
 
         mZenModeConfig.suppressedVisualEffects = 0;
@@ -221,14 +228,15 @@
     @Test
     public void testRemoveBubble() {
         mBubbleController.updateBubble(mRow.getEntry());
-        assertNotNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
+        assertNotNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
         assertTrue(mBubbleController.hasBubbles());
         verify(mNotificationEntryManager).updateNotifications(any());
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true);
 
-        mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleController.removeBubble(
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mStatusBarWindowController.getBubblesShowing());
-        assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
+        assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
         verify(mNotificationEntryManager, times(2)).updateNotifications(anyString());
         verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
     }
@@ -239,18 +247,20 @@
         mBubbleController.updateBubble(mRow.getEntry());
 
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         // Make it look like dismissed notif
-        mBubbleData.getBubbleWithKey(mRow.getEntry().key).setShowInShadeWhenBubble(false);
+        mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).setShowInShadeWhenBubble(false);
 
         // Now remove the bubble
-        mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleController.removeBubble(
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
 
         // Since the notif is dismissed, once the bubble is removed, performRemoveNotification gets
         // called to really remove the notif
         verify(mNotificationEntryManager, times(1)).performRemoveNotification(
-                mRow.getEntry().notification, UNDEFINED_DISMISS_REASON);
+                mRow.getEntry().getSbn(), UNDEFINED_DISMISS_REASON);
         assertFalse(mBubbleController.hasBubbles());
     }
 
@@ -258,17 +268,17 @@
     public void testDismissStack() {
         mBubbleController.updateBubble(mRow.getEntry());
         verify(mNotificationEntryManager, times(1)).updateNotifications(any());
-        assertNotNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
+        assertNotNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
         mBubbleController.updateBubble(mRow2.getEntry());
         verify(mNotificationEntryManager, times(2)).updateNotifications(any());
-        assertNotNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().key));
+        assertNotNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().getKey()));
         assertTrue(mBubbleController.hasBubbles());
 
         mBubbleController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mStatusBarWindowController.getBubblesShowing());
         verify(mNotificationEntryManager, times(3)).updateNotifications(any());
-        assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
-        assertNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().key));
+        assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
+        assertNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().getKey()));
     }
 
     @Test
@@ -281,22 +291,24 @@
 
         // We should have bubbles & their notifs should not be suppressed
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
         assertFalse(mStatusBarWindowController.getBubbleExpanded());
 
         // Expand the stack
         BubbleStackView stackView = mBubbleController.getStackView();
         mBubbleController.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
         assertTrue(mStatusBarWindowController.getBubbleExpanded());
 
         // Make sure the notif is suppressed
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         // Collapse
         mBubbleController.collapseStack();
-        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
         assertFalse(mBubbleController.isStackExpanded());
         assertFalse(mStatusBarWindowController.getBubbleExpanded());
     }
@@ -311,30 +323,33 @@
 
         // We should have bubbles & their notifs should not be suppressed
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
         assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
-                mRow2.getEntry().key));
+                mRow.getEntry().getKey()));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow2.getEntry().getKey()));
 
         // Expand
         BubbleStackView stackView = mBubbleController.getStackView();
         mBubbleController.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
 
         // Last added is the one that is expanded
         assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow2.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow2.getEntry().getKey()));
 
         // Switch which bubble is expanded
-        mBubbleController.selectBubble(mRow.getEntry().key);
-        stackView.setExpandedBubble(mRow.getEntry().key);
+        mBubbleController.selectBubble(mRow.getEntry().getKey());
+        stackView.setExpandedBubble(mRow.getEntry().getKey());
         assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         // collapse for previous bubble
-        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
         // expand for selected bubble
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
 
         // Collapse
         mBubbleController.collapseStack();
@@ -349,18 +364,20 @@
 
         // We should have bubbles & their notifs should not be suppressed
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
-        assertTrue(mBubbleData.getBubbleWithKey(mRow.getEntry().key).showBubbleDot());
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+        assertTrue(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).showBubbleDot());
 
         // Expand
         mBubbleController.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
 
         // Notif is suppressed after expansion
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
         // Notif shouldn't show dot after expansion
-        assertFalse(mBubbleData.getBubbleWithKey(mRow.getEntry().key).showBubbleDot());
+        assertFalse(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).showBubbleDot());
     }
 
     @Test
@@ -371,28 +388,31 @@
 
         // We should have bubbles & their notifs should not be suppressed
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
-        assertTrue(mBubbleData.getBubbleWithKey(mRow.getEntry().key).showBubbleDot());
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+        assertTrue(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).showBubbleDot());
 
         // Expand
         BubbleStackView stackView = mBubbleController.getStackView();
         mBubbleController.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
 
         // Notif is suppressed after expansion
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
         // Notif shouldn't show dot after expansion
-        assertFalse(mBubbleData.getBubbleWithKey(mRow.getEntry().key).showBubbleDot());
+        assertFalse(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).showBubbleDot());
 
         // Send update
         mEntryListener.onPreEntryUpdated(mRow.getEntry());
 
         // Nothing should have changed
         // Notif is suppressed after expansion
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
         // Notif shouldn't show dot after expansion
-        assertFalse(mBubbleData.getBubbleWithKey(mRow.getEntry().key).showBubbleDot());
+        assertFalse(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).showBubbleDot());
     }
 
     @Test
@@ -409,27 +429,28 @@
         mBubbleController.expandStack();
 
         assertTrue(mBubbleController.isStackExpanded());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
 
         // Last added is the one that is expanded
         assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow2.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow2.getEntry().getKey()));
 
         // Dismiss currently expanded
         mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
                 BubbleController.DISMISS_USER_GESTURE);
-        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
 
         // Make sure first bubble is selected
         assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
 
         // Dismiss that one
         mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
                 BubbleController.DISMISS_USER_GESTURE);
 
         // Make sure state changes and collapse happens
-        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
         verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
         assertFalse(mBubbleController.hasBubbles());
     }
@@ -446,7 +467,7 @@
 
         // Expansion shouldn't change
         verify(mBubbleExpandListener, never()).onBubbleExpandChanged(false /* expanded */,
-                mRow.getEntry().key);
+                mRow.getEntry().getKey());
         assertFalse(mBubbleController.isStackExpanded());
 
         // # of bubbles should change
@@ -464,7 +485,7 @@
 
         // Expansion should change
         verify(mBubbleExpandListener).onBubbleExpandChanged(true /* expanded */,
-                mRow.getEntry().key);
+                mRow.getEntry().getKey());
         assertTrue(mBubbleController.isStackExpanded());
 
         // # of bubbles should change
@@ -481,7 +502,8 @@
         mBubbleController.updateBubble(mRow.getEntry());
 
         // Should not be suppressed because we weren't forground
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
         // # of bubbles should change
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */);
     }
@@ -496,7 +518,8 @@
         mBubbleController.updateBubble(mRow.getEntry());
 
         // Notif should be suppressed because we were foreground
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         // # of bubbles should change
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */);
@@ -504,13 +527,14 @@
 
     @Test
     public void testExpandStackAndSelectBubble_removedFirst() {
-        final String key = mRow.getEntry().key;
+        final String key = mRow.getEntry().getKey();
 
         mEntryListener.onPendingEntryAdded(mRow.getEntry());
         mBubbleController.updateBubble(mRow.getEntry());
 
         // Simulate notification cancellation.
-        mRemoveInterceptor.onNotificationRemoveRequested(mRow.getEntry().key, REASON_APP_CANCEL);
+        mRemoveInterceptor.onNotificationRemoveRequested(
+                mRow.getEntry().getKey(), REASON_APP_CANCEL);
 
         mBubbleController.expandStackAndSelectBubble(key);
     }
@@ -518,8 +542,9 @@
     @Test
     public void testMarkNewNotificationAsShowInShade() {
         mEntryListener.onPendingEntryAdded(mRow.getEntry());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
-        assertTrue(mBubbleData.getBubbleWithKey(mRow.getEntry().key).showBubbleDot());
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+        assertTrue(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).showBubbleDot());
     }
 
     @Test
@@ -534,14 +559,15 @@
     @Test
     public void testDeleteIntent_removeBubble_aged() throws PendingIntent.CanceledException {
         mBubbleController.updateBubble(mRow.getEntry());
-        mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_AGED);
+        mBubbleController.removeBubble(mRow.getEntry().getKey(), BubbleController.DISMISS_AGED);
         verify(mDeleteIntent, never()).send();
     }
 
     @Test
     public void testDeleteIntent_removeBubble_user() throws PendingIntent.CanceledException {
         mBubbleController.updateBubble(mRow.getEntry());
-        mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleController.removeBubble(
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         verify(mDeleteIntent, times(1)).send();
     }
 
@@ -559,7 +585,7 @@
         mBubbleController.updateBubble(mRow.getEntry());
         assertTrue(mBubbleController.hasBubbles());
 
-        mRow.getEntry().notification.getNotification().flags &= ~FLAG_BUBBLE;
+        mRow.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
         mEntryListener.onPreEntryUpdated(mRow.getEntry());
 
         assertFalse(mBubbleController.hasBubbles());
@@ -574,7 +600,7 @@
         assertTrue(mBubbleController.hasBubbles());
 
         boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
-                mRow.getEntry().key, REASON_APP_CANCEL);
+                mRow.getEntry().getKey(), REASON_APP_CANCEL);
 
         // Cancels always remove so no need to intercept
         assertFalse(intercepted);
@@ -587,15 +613,17 @@
         mBubbleController.updateBubble(mRow.getEntry());
 
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
-                mRow.getEntry().key, REASON_CANCEL_ALL);
+                mRow.getEntry().getKey(), REASON_CANCEL_ALL);
 
         // Intercept!
         assertTrue(intercepted);
         // Should update show in shade state
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         verify(mNotificationEntryManager, never()).performRemoveNotification(
                 any(), anyInt());
@@ -608,15 +636,17 @@
         mBubbleController.updateBubble(mRow.getEntry());
 
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
-                mRow.getEntry().key, REASON_CANCEL);
+                mRow.getEntry().getKey(), REASON_CANCEL);
 
         // Intercept!
         assertTrue(intercepted);
         // Should update show in shade state
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         verify(mNotificationEntryManager, never()).performRemoveNotification(
                 any(), anyInt());
@@ -629,15 +659,17 @@
         mBubbleController.updateBubble(mRow.getEntry());
 
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         // Dismiss the bubble
-        mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleController.removeBubble(
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mBubbleController.hasBubbles());
 
         // Dismiss the notification
         boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
-                mRow.getEntry().key, REASON_CANCEL);
+                mRow.getEntry().getKey(), REASON_CANCEL);
 
         // It's no longer a bubble so we shouldn't intercept
         assertFalse(intercepted);
@@ -687,7 +719,7 @@
      */
     private void setMetadataFlags(NotificationEntry entry, int flag, boolean enableFlag) {
         Notification.BubbleMetadata bubbleMetadata =
-                entry.notification.getNotification().getBubbleMetadata();
+                entry.getSbn().getNotification().getBubbleMetadata();
         int flags = bubbleMetadata.getFlags();
         if (enableFlag) {
             flags |= flag;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
index 96ee079..67f65e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
@@ -842,14 +842,14 @@
     }
 
     private void setPostTime(NotificationEntry entry, long postTime) {
-        when(entry.notification.getPostTime()).thenReturn(postTime);
+        when(entry.getSbn().getPostTime()).thenReturn(postTime);
     }
 
     private void setOngoing(NotificationEntry entry, boolean ongoing) {
         if (ongoing) {
-            entry.notification.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
+            entry.getSbn().getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
         } else {
-            entry.notification.getNotification().flags &= ~Notification.FLAG_FOREGROUND_SERVICE;
+            entry.getSbn().getNotification().flags &= ~Notification.FLAG_FOREGROUND_SERVICE;
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ClassifierTest.java
index d011e48..3ba5d1a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ClassifierTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.classifier.brightline;
 
+import static com.android.systemui.classifier.Classifier.UNLOCK;
+
 import android.util.DisplayMetrics;
 import android.view.MotionEvent;
 
@@ -42,6 +44,7 @@
         displayMetrics.widthPixels = 1000;
         displayMetrics.heightPixels = 1000;
         mDataProvider = new FalsingDataProvider(displayMetrics);
+        mDataProvider.setInteractionType(UNLOCK);
     }
 
     @After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/PointerCountClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/PointerCountClassifierTest.java
index 341b74b..96b2028 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/PointerCountClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/PointerCountClassifierTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.classifier.brightline;
 
+import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
+
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
 
@@ -74,4 +76,21 @@
         motionEvent.recycle();
         assertThat(mClassifier.isFalseTouch(), is(true));
     }
+
+    @Test
+    public void testPass_multiPointerDragDown() {
+        MotionEvent.PointerProperties[] pointerProperties =
+                MotionEvent.PointerProperties.createArray(2);
+        pointerProperties[0].id = 0;
+        pointerProperties[1].id = 1;
+        MotionEvent.PointerCoords[] pointerCoords = MotionEvent.PointerCoords.createArray(2);
+        MotionEvent motionEvent = MotionEvent.obtain(
+                1, 1, MotionEvent.ACTION_DOWN, 2, pointerProperties, pointerCoords, 0, 0, 0, 0, 0,
+                0,
+                0, 0);
+        mClassifier.onTouchEvent(motionEvent);
+        motionEvent.recycle();
+        getDataProvider().setInteractionType(QUICK_SETTINGS);
+        assertThat(mClassifier.isFalseTouch(), is(false));
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
index 1ce0172..98ec4594 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
@@ -20,13 +20,11 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.app.Instrumentation;
 import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.Handler;
 import android.os.Looper;
@@ -34,7 +32,6 @@
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
@@ -45,23 +42,24 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 public class DozeDockHandlerTest extends SysuiTestCase {
-    private DozeDockHandler mDockHandler;
+    @Mock
     private DozeMachine mMachine;
-    private DozeHostFake mHost;
+    @Mock
+    private DozeHost mHost;
     private AmbientDisplayConfiguration mConfig;
-    private Instrumentation mInstrumentation;
     private DockManagerFake mDockManagerFake;
+    private DozeDockHandler mDockHandler;
 
     @Before
     public void setUp() throws Exception {
-        mInstrumentation = InstrumentationRegistry.getInstrumentation();
-        mMachine = mock(DozeMachine.class);
-        mHost = spy(new DozeHostFake());
+        MockitoAnnotations.initMocks(this);
         mConfig = DozeConfigurationUtil.createMockConfig();
         doReturn(false).when(mConfig).alwaysOnEnabled(anyInt());
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
deleted file mode 100644
index abfa755..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.doze;
-
-import android.annotation.NonNull;
-
-/**
- * A rudimentary fake for DozeHost.
- */
-class DozeHostFake implements DozeHost {
-    Callback callback;
-    boolean pulseExtended;
-    boolean animateWakeup;
-    boolean animateScreenOff;
-    boolean dozing;
-    float doubleTapX;
-    float doubleTapY;
-    float aodDimmingScrimOpacity;
-
-    @Override
-    public void addCallback(@NonNull Callback callback) {
-        this.callback = callback;
-    }
-
-    @Override
-    public void removeCallback(@NonNull Callback callback) {
-        this.callback = null;
-    }
-
-    @Override
-    public void startDozing() {
-        dozing = true;
-    }
-
-    @Override
-    public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) {
-        throw new RuntimeException("not implemented");
-    }
-
-    @Override
-    public void stopDozing() {
-        dozing = false;
-    }
-
-    @Override
-    public void dozeTimeTick() {
-        // Nothing to do in here. Real host would just update the UI.
-    }
-
-    @Override
-    public boolean isPowerSaveActive() {
-        return false;
-    }
-
-    @Override
-    public boolean isPulsingBlocked() {
-        return false;
-    }
-
-    @Override
-    public boolean isProvisioned() {
-        return false;
-    }
-
-    @Override
-    public boolean isBlockingDoze() {
-        return false;
-    }
-
-    @Override
-    public void onIgnoreTouchWhilePulsing(boolean ignore) {
-    }
-
-    @Override
-    public void extendPulse(int reason) {
-        pulseExtended = true;
-    }
-
-    @Override
-    public void stopPulsing() {}
-
-    @Override
-    public void setAnimateWakeup(boolean animateWakeup) {
-        this.animateWakeup = animateWakeup;
-    }
-
-    @Override
-    public void setAnimateScreenOff(boolean animateScreenOff) {
-        this.animateScreenOff = animateScreenOff;
-    }
-
-    @Override
-    public void onSlpiTap(float x, float y) {
-        doubleTapX = y;
-        doubleTapY = y;
-    }
-
-    @Override
-    public void setDozeScreenBrightness(int value) {
-    }
-
-    @Override
-    public void setAodDimmingScrim(float scrimOpacity) {
-        aodDimmingScrimOpacity = scrimOpacity;
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
index aa62e9a..316b891 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -30,6 +30,11 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
 
 import android.content.Intent;
 import android.os.PowerManager;
@@ -45,6 +50,8 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -55,22 +62,27 @@
     static final int[] SENSOR_TO_OPACITY = new int[]{-1, 10, 0, 0, 0};
 
     DozeServiceFake mServiceFake;
-    DozeScreenBrightness mScreen;
     FakeSensorManager.FakeGenericSensor mSensor;
     FakeSensorManager mSensorManager;
-    DozeHostFake mHostFake;
+    @Mock
+    DozeHost mDozeHost;
+    DozeScreenBrightness mScreen;
 
     @Before
     public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
         Settings.System.putIntForUser(mContext.getContentResolver(),
                 Settings.System.SCREEN_BRIGHTNESS, DEFAULT_BRIGHTNESS,
                 UserHandle.USER_CURRENT);
+        doAnswer(invocation -> {
+            ((Runnable) invocation.getArgument(0)).run();
+            return null;
+        }).when(mDozeHost).prepareForGentleSleep(any());
         mServiceFake = new DozeServiceFake();
-        mHostFake = new DozeHostFake();
         mSensorManager = new FakeSensorManager(mContext);
         mSensor = mSensorManager.getFakeLightSensor();
         mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
-                mSensor.getSensor(), mHostFake, null /* handler */,
+                mSensor.getSensor(), mDozeHost, null /* handler */,
                 DEFAULT_BRIGHTNESS, SENSOR_TO_BRIGHTNESS, SENSOR_TO_OPACITY,
                 true /* debuggable */);
     }
@@ -173,7 +185,7 @@
     @Test
     public void testNullSensor() throws Exception {
         mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
-                null /* sensor */, mHostFake, null /* handler */,
+                null /* sensor */, mDozeHost, null /* handler */,
                 DEFAULT_BRIGHTNESS, SENSOR_TO_BRIGHTNESS, SENSOR_TO_OPACITY,
                 true /* debuggable */);
 
@@ -203,26 +215,7 @@
         mSensor.sendSensorEvent(0);
 
         assertEquals(1, mServiceFake.screenBrightness);
-        assertEquals(10/255f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
-    }
-
-    @Test
-    public void pausingAod_softBlanks() throws Exception {
-        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
-        mScreen.transitionTo(INITIALIZED, DOZE_AOD);
-
-        mSensor.sendSensorEvent(2);
-
-        mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
-        mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
-
-        assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
-
-        mSensor.sendSensorEvent(0);
-        assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
-
-        mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD);
-        assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
+        verify(mDozeHost).setAodDimmingScrim(eq(10f / 255f));
     }
 
     @Test
@@ -232,8 +225,9 @@
         mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
         mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
 
+        reset(mDozeHost);
         mSensor.sendSensorEvent(1);
-        assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
+        verify(mDozeHost).setAodDimmingScrim(eq(1f));
     }
 
     @Test
@@ -241,11 +235,12 @@
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
         mScreen.transitionTo(INITIALIZED, DOZE_AOD);
         mScreen.transitionTo(DOZE_AOD, DOZE);
-        assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
+        verify(mDozeHost).setAodDimmingScrim(eq(1f));
 
+        reset(mDozeHost);
         mScreen.transitionTo(DOZE, DOZE_AOD);
         mSensor.sendSensorEvent(2);
-        assertEquals(0f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
+        verify(mDozeHost).setAodDimmingScrim(eq(0f));
     }
 
     @Test
@@ -260,11 +255,10 @@
 
         mSensor.sendSensorEvent(0);
 
+        reset(mDozeHost);
         mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD);
-
         mSensor.sendSensorEvent(2);
-
-        assertEquals(0f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
+        verify(mDozeHost).setAodDimmingScrim(eq(0f));
     }
 
     @Test
@@ -273,11 +267,11 @@
         mScreen.transitionTo(INITIALIZED, DOZE_AOD);
 
         mSensor.sendSensorEvent(2);
-
         mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
         mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
-        mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD);
 
-        assertEquals(0f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
+        reset(mDozeHost);
+        mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD);
+        verify(mDozeHost).setAodDimmingScrim(eq(0f));
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
index bfd448a..b92f173 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
@@ -18,6 +18,8 @@
 
 import static com.android.systemui.doze.DozeMachine.State.DOZE;
 import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSING;
 import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSING;
 import static com.android.systemui.doze.DozeMachine.State.DOZE_REQUEST_PULSE;
 import static com.android.systemui.doze.DozeMachine.State.FINISH;
@@ -30,6 +32,9 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.os.Looper;
@@ -46,6 +51,7 @@
 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;
 
@@ -53,12 +59,14 @@
 @SmallTest
 public class DozeScreenStateTest extends SysuiTestCase {
 
-    DozeServiceFake mServiceFake;
-    DozeScreenState mScreen;
-    FakeHandler mHandlerFake;
+    private DozeServiceFake mServiceFake;
+    private FakeHandler mHandlerFake;
     @Mock
-    DozeParameters mDozeParameters;
-    WakeLockFake mWakeLock;
+    private DozeHost mDozeHost;
+    @Mock
+    private DozeParameters mDozeParameters;
+    private WakeLockFake mWakeLock;
+    private DozeScreenState mScreen;
 
     @Before
     public void setUp() throws Exception {
@@ -68,7 +76,8 @@
         mServiceFake = new DozeServiceFake();
         mHandlerFake = new FakeHandler(Looper.getMainLooper());
         mWakeLock = new WakeLockFake();
-        mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeParameters, mWakeLock);
+        mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeHost, mDozeParameters,
+                mWakeLock);
     }
 
     @Test
@@ -183,4 +192,20 @@
         assertThat(mWakeLock.isHeld(), is(false));
     }
 
+    @Test
+    public void test_animatesPausing() {
+        ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
+        doAnswer(invocation -> null).when(mDozeHost).prepareForGentleSleep(captor.capture());
+        mHandlerFake.setMode(QUEUEING);
+
+        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+        mScreen.transitionTo(INITIALIZED, DOZE_AOD_PAUSING);
+        mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
+
+        mHandlerFake.dispatchQueuedMessages();
+        verify(mDozeHost).prepareForGentleSleep(eq(captor.getValue()));
+        captor.getValue().run();
+        assertEquals(Display.STATE_OFF, mServiceFake.screenState);
+    }
+
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index e5ae6d5..756227e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -20,6 +20,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -50,14 +51,22 @@
 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)
 @RunWithLooper(setAsMainLooper = true)
 public class DozeTriggersTest extends SysuiTestCase {
-    private DozeTriggers mTriggers;
+
+    @Mock
     private DozeMachine mMachine;
-    private DozeHostFake mHost;
+    @Mock
+    private DozeHost mHost;
+    @Mock
+    private AlarmManager mAlarmManager;
+    private DozeTriggers mTriggers;
     private FakeSensorManager mSensors;
     private Sensor mTapSensor;
     private DockManager mDockManagerFake;
@@ -65,9 +74,7 @@
 
     @Before
     public void setUp() throws Exception {
-        mMachine = mock(DozeMachine.class);
-        AlarmManager alarmManager = mock(AlarmManager.class);
-        mHost = spy(new DozeHostFake());
+        MockitoAnnotations.initMocks(this);
         AmbientDisplayConfiguration config = DozeConfigurationUtil.createMockConfig();
         DozeParameters parameters = DozeConfigurationUtil.createMockParameters();
         mSensors = spy(new FakeSensorManager(mContext));
@@ -76,9 +83,9 @@
         mDockManagerFake = mock(DockManager.class);
         AsyncSensorManager asyncSensorManager =
                 new AsyncSensorManager(mSensors, null, new Handler());
-        mProximitySensor = new FakeProximitySensor(getContext(), asyncSensorManager);
+        mProximitySensor = new FakeProximitySensor(getContext().getResources(), asyncSensorManager);
 
-        mTriggers = new DozeTriggers(mContext, mMachine, mHost, alarmManager, config, parameters,
+        mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, config, parameters,
                 asyncSensorManager, Handler.createAsync(Looper.myLooper()), wakeLock, true,
                 mDockManagerFake, mProximitySensor, mock(DozeLog.class));
         waitForSensorManager();
@@ -87,19 +94,21 @@
     @Test
     public void testOnNotification_stillWorksAfterOneFailedProxCheck() throws Exception {
         when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
+        ArgumentCaptor<DozeHost.Callback> captor = ArgumentCaptor.forClass(DozeHost.Callback.class);
+        doAnswer(invocation -> null).when(mHost).addCallback(captor.capture());
 
         mTriggers.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
         mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
         clearInvocations(mMachine);
 
         mProximitySensor.setLastEvent(new ProximitySensor.ProximityEvent(true, 1));
-        mHost.callback.onNotificationAlerted(null /* pulseSuppressedListener */);
+        captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */);
         mProximitySensor.alertListeners();
 
         verify(mMachine, never()).requestState(any());
         verify(mMachine, never()).requestPulse(anyInt());
 
-        mHost.callback.onNotificationAlerted(null /* pulseSuppressedListener */);
+        captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */);
         waitForSensorManager();
         mProximitySensor.setLastEvent(new ProximitySensor.ProximityEvent(false, 2));
         mProximitySensor.alertListeners();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
new file mode 100644
index 0000000..c385e8f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.keyguard;
+
+import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.SystemUIFactory;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class KeyguardViewMediatorTest extends SysuiTestCase {
+    private KeyguardViewMediator mViewMediator;
+
+    private @Mock DevicePolicyManager mDevicePolicyManager;
+    private @Mock LockPatternUtils mLockPatternUtils;
+    private @Mock KeyguardUpdateMonitor mUpdateMonitor;
+    private @Mock StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    private @Mock StatusBarWindowController mStatusBarWindowController;
+    private @Mock SystemUIFactory mSystemUIFactory;
+
+    private FalsingManagerFake mFalsingManager;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mFalsingManager = new FalsingManagerFake();
+
+        mDependency.injectTestDependency(FalsingManager.class, mFalsingManager);
+        mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mUpdateMonitor);
+        mDependency.injectTestDependency(StatusBarWindowController.class,
+                mStatusBarWindowController);
+
+        when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager);
+        when(mSystemUIFactory.createStatusBarKeyguardViewManager(
+                any(Context.class),
+                any(ViewMediatorCallback.class),
+                any(LockPatternUtils.class))).thenReturn(mStatusBarKeyguardViewManager);
+
+        TestableLooper.get(this).runWithLooper(() -> {
+            mViewMediator = new KeyguardViewMediator(
+                    mContext, mFalsingManager, mLockPatternUtils, mSystemUIFactory);
+        });
+    }
+
+    @Test
+    public void testOnGoingToSleep_UpdatesKeyguardGoingAway() {
+        mViewMediator.start();
+        mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_USER);
+        verify(mUpdateMonitor).setKeyguardGoingAway(false);
+        verify(mStatusBarWindowController).setKeyguardGoingAway(false);
+    }
+}
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
new file mode 100644
index 0000000..4becd52
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
@@ -0,0 +1,128 @@
+/*
+ * 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.qs.external
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
+import android.content.pm.ServiceInfo
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.Icon
+import android.service.quicksettings.IQSTileService
+import android.service.quicksettings.Tile
+import android.test.suitebuilder.annotation.SmallTest
+import android.view.IWindowManager
+import androidx.test.runner.AndroidJUnit4
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.qs.QSTileHost
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.any
+import org.mockito.Mockito.mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CustomTileTest : SysuiTestCase() {
+
+    companion object {
+        const val packageName = "test_package"
+        const val className = "test_class"
+        val componentName = ComponentName(packageName, className)
+        val TILE_SPEC = CustomTile.toSpec(componentName)
+    }
+
+    @Mock private lateinit var mTileHost: QSTileHost
+    @Mock private lateinit var mTileService: IQSTileService
+    @Mock private lateinit var mTileServices: TileServices
+    @Mock private lateinit var mTileServiceManager: TileServiceManager
+    @Mock private lateinit var mWindowService: IWindowManager
+    @Mock private lateinit var mPackageManager: PackageManager
+    @Mock private lateinit var mApplicationInfo: ApplicationInfo
+    @Mock private lateinit var mServiceInfo: ServiceInfo
+
+    private lateinit var customTile: CustomTile
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        mContext.addMockSystemService("window", mWindowService)
+        mContext.setMockPackageManager(mPackageManager)
+        `when`(mTileHost.tileServices).thenReturn(mTileServices)
+        `when`(mTileHost.context).thenReturn(mContext)
+        `when`(mTileServices.getTileWrapper(any(CustomTile::class.java)))
+                .thenReturn(mTileServiceManager)
+        `when`(mTileServiceManager.tileService).thenReturn(mTileService)
+        `when`(mPackageManager.getApplicationInfo(anyString(), anyInt()))
+                .thenReturn(mApplicationInfo)
+
+        `when`(mPackageManager.getServiceInfo(any(ComponentName::class.java), anyInt()))
+                .thenReturn(mServiceInfo)
+        mServiceInfo.applicationInfo = mApplicationInfo
+
+        customTile = CustomTile.create(mTileHost, TILE_SPEC)
+    }
+
+    @Test
+    fun testBooleanTileHasBooleanState() {
+        `when`(mTileServiceManager.isBooleanTile).thenReturn(true)
+        customTile = CustomTile.create(mTileHost, TILE_SPEC)
+
+        assertTrue(customTile.state is QSTile.BooleanState)
+        assertTrue(customTile.newTileState() is QSTile.BooleanState)
+    }
+
+    @Test
+    fun testRegularTileHasNotBooleanState() {
+        assertFalse(customTile.state is QSTile.BooleanState)
+        assertFalse(customTile.newTileState() is QSTile.BooleanState)
+    }
+
+    @Test
+    fun testValueUpdatedInBooleanTile() {
+        `when`(mTileServiceManager.isBooleanTile).thenReturn(true)
+        customTile = CustomTile.create(mTileHost, TILE_SPEC)
+        customTile.qsTile.icon = mock(Icon::class.java)
+        `when`(customTile.qsTile.icon.loadDrawable(any(Context::class.java)))
+                .thenReturn(mock(Drawable::class.java))
+
+        val state = customTile.newTileState()
+        assertTrue(state is QSTile.BooleanState)
+
+        customTile.qsTile.state = Tile.STATE_INACTIVE
+        customTile.handleUpdateState(state, null)
+        assertFalse((state as QSTile.BooleanState).value)
+
+        customTile.qsTile.state = Tile.STATE_ACTIVE
+        customTile.handleUpdateState(state, null)
+        assertTrue(state.value)
+
+        customTile.qsTile.state = Tile.STATE_UNAVAILABLE
+        customTile.handleUpdateState(state, null)
+        assertFalse(state.value)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
index f35295c..11b0c69 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
@@ -101,6 +101,7 @@
             defaultServiceInfo = new ServiceInfo();
             defaultServiceInfo.metaData = new Bundle();
             defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_ACTIVE_TILE, true);
+            defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_BOOLEAN_TILE, true);
         }
         when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt(), anyInt()))
                 .thenReturn(defaultServiceInfo);
@@ -237,4 +238,9 @@
         verifyBind(2);
         verify(mMockTileService, times(2)).onStartListening();
     }
+
+    @Test
+    public void testBooleanTile() throws Exception {
+        assertTrue(mStateManager.isBooleanTile());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
index cf5a12f..c6dd232 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
@@ -141,9 +141,9 @@
     public void testShowNotification_addsEntry() {
         mAlertingNotificationManager.showNotification(mEntry);
 
-        assertTrue(mAlertingNotificationManager.isAlerting(mEntry.key));
+        assertTrue(mAlertingNotificationManager.isAlerting(mEntry.getKey()));
         assertTrue(mAlertingNotificationManager.hasNotifications());
-        assertEquals(mEntry, mAlertingNotificationManager.getEntry(mEntry.key));
+        assertEquals(mEntry, mAlertingNotificationManager.getEntry(mEntry.getKey()));
     }
 
     @Test
@@ -155,7 +155,7 @@
         TestableLooper.get(this).processMessages(1);
 
         assertFalse("Test timed out", mTimedOut);
-        assertFalse(mAlertingNotificationManager.isAlerting(mEntry.key));
+        assertFalse(mAlertingNotificationManager.isAlerting(mEntry.getKey()));
     }
 
     @Test
@@ -163,9 +163,10 @@
         mAlertingNotificationManager.showNotification(mEntry);
 
         // Try to remove but defer, since the notification has not been shown long enough.
-        mAlertingNotificationManager.removeNotification(mEntry.key, false /* releaseImmediately */);
+        mAlertingNotificationManager.removeNotification(
+                mEntry.getKey(), false /* releaseImmediately */);
 
-        assertTrue(mAlertingNotificationManager.isAlerting(mEntry.key));
+        assertTrue(mAlertingNotificationManager.isAlerting(mEntry.getKey()));
     }
 
     @Test
@@ -173,9 +174,10 @@
         mAlertingNotificationManager.showNotification(mEntry);
 
         // Remove forcibly with releaseImmediately = true.
-        mAlertingNotificationManager.removeNotification(mEntry.key, true /* releaseImmediately */);
+        mAlertingNotificationManager.removeNotification(
+                mEntry.getKey(), true /* releaseImmediately */);
 
-        assertFalse(mAlertingNotificationManager.isAlerting(mEntry.key));
+        assertFalse(mAlertingNotificationManager.isAlerting(mEntry.getKey()));
     }
 
     @Test
@@ -199,7 +201,7 @@
         mAlertingNotificationManager.showNotification(mEntry);
 
         // The entry has just been added so we should not remove immediately.
-        assertFalse(mAlertingNotificationManager.canRemoveImmediately(mEntry.key));
+        assertFalse(mAlertingNotificationManager.canRemoveImmediately(mEntry.getKey()));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryHelper.java
index 33b0d2c..2420e57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryHelper.java
@@ -36,7 +36,7 @@
         private final NotificationEntry mTarget;
 
         private ModifiedRankingBuilder(NotificationEntry target) {
-            super(target.ranking());
+            super(target.getRanking());
             mTarget = target;
         }
 
@@ -52,14 +52,14 @@
         private final NotificationEntry mTarget;
 
         private ModifiedSbnBuilder(NotificationEntry target) {
-            super(target.sbn());
+            super(target.getSbn());
             mTarget = target;
         }
 
         @Override
         public StatusBarNotification build() {
             final StatusBarNotification sbn = super.build();
-            mTarget.setNotification(sbn);
+            mTarget.setSbn(sbn);
             return sbn;
         }
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
index 28a7e40..9b860c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
@@ -523,7 +523,7 @@
         modifyRanking(entry)
                 .setCanBubble(true)
                 .build();
-        entry.sbn().getNotification().flags |= FLAG_BUBBLE;
+        entry.getSbn().getNotification().flags |= FLAG_BUBBLE;
 
         assertThat(mNotifInterruptionStateProvider.shouldBubbleUp(entry)).isFalse();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
index 852ddb2..2514c93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
@@ -97,7 +97,7 @@
     @Test
     public void testPerformOnRemoveNotification() {
         when(mController.isRemoteInputActive(mEntry)).thenReturn(true);
-        mRemoteInputManager.onPerformRemoveNotification(mEntry, mEntry.key());
+        mRemoteInputManager.onPerformRemoveNotification(mEntry, mEntry.getKey());
 
         verify(mController).removeRemoteInput(mEntry, null);
     }
@@ -112,7 +112,7 @@
     @Test
     public void testShouldExtendLifetime_isSpinning() {
         NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY = true;
-        when(mController.isSpinning(mEntry.key)).thenReturn(true);
+        when(mController.isSpinning(mEntry.getKey())).thenReturn(true);
 
         assertTrue(mRemoteInputHistoryExtender.shouldExtendLifetime(mEntry));
     }
@@ -128,7 +128,7 @@
     @Test
     public void testShouldExtendLifetime_smartReplySending() {
         NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY = true;
-        when(mSmartReplyController.isSendingSmartReply(mEntry.key)).thenReturn(true);
+        when(mSmartReplyController.isSendingSmartReply(mEntry.getKey())).thenReturn(true);
 
         assertTrue(mSmartReplyHistoryExtender.shouldExtendLifetime(mEntry));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index cb4096c..90bd0e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -326,7 +326,7 @@
                 .build();
 
         entry.setRow(row);
-        entry.createIcons(mContext, entry.sbn());
+        entry.createIcons(mContext, entry.getSbn());
         row.setEntry(entry);
         row.getNotificationInflater().addInflationFlags(extraInflationFlags);
         NotificationContentInflaterTest.runThenWaitForInflation(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 6efa57d..18649bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -143,11 +143,11 @@
                 Lists.newArrayList(entry0, entry1, entry2));
 
         // Set up group manager to report that they should be bundled now.
-        when(mGroupManager.isChildInGroupWithSummary(entry0.notification)).thenReturn(false);
-        when(mGroupManager.isChildInGroupWithSummary(entry1.notification)).thenReturn(true);
-        when(mGroupManager.isChildInGroupWithSummary(entry2.notification)).thenReturn(true);
-        when(mGroupManager.getGroupSummary(entry1.notification)).thenReturn(entry0);
-        when(mGroupManager.getGroupSummary(entry2.notification)).thenReturn(entry0);
+        when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false);
+        when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(true);
+        when(mGroupManager.isChildInGroupWithSummary(entry2.getSbn())).thenReturn(true);
+        when(mGroupManager.getGroupSummary(entry1.getSbn())).thenReturn(entry0);
+        when(mGroupManager.getGroupSummary(entry2.getSbn())).thenReturn(entry0);
 
         // Run updateNotifications - the view hierarchy should be reorganized.
         mViewHierarchyManager.updateNotificationViews();
@@ -172,9 +172,9 @@
                 Lists.newArrayList(entry0, entry1, entry2));
 
         // Set up group manager to report that they should not be bundled now.
-        when(mGroupManager.isChildInGroupWithSummary(entry0.notification)).thenReturn(false);
-        when(mGroupManager.isChildInGroupWithSummary(entry1.notification)).thenReturn(false);
-        when(mGroupManager.isChildInGroupWithSummary(entry2.notification)).thenReturn(false);
+        when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false);
+        when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(false);
+        when(mGroupManager.isChildInGroupWithSummary(entry2.getSbn())).thenReturn(false);
 
         // Run updateNotifications - the view hierarchy should be reorganized.
         mViewHierarchyManager.updateNotificationViews();
@@ -201,9 +201,9 @@
                 Lists.newArrayList(entry0, entry1));
 
         // Set up group manager to report a suppressed summary now.
-        when(mGroupManager.isChildInGroupWithSummary(entry0.notification)).thenReturn(false);
-        when(mGroupManager.isChildInGroupWithSummary(entry1.notification)).thenReturn(false);
-        when(mGroupManager.isSummaryOfSuppressedGroup(entry0.notification)).thenReturn(true);
+        when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false);
+        when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(false);
+        when(mGroupManager.isSummaryOfSuppressedGroup(entry0.getSbn())).thenReturn(true);
 
         // Run updateNotifications - the view hierarchy should be reorganized.
         mViewHierarchyManager.updateNotificationViews();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index e52a258..ebdf851 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -250,7 +250,7 @@
                 .setNotification(n.build())
                 .setUser(new UserHandle(ActivityManager.getCurrentUser()))
                 .build();
-        mSbn = mEntry.sbn();
+        mSbn = mEntry.getSbn();
 
         mEntry.expandedIcon = mock(StatusBarIconView.class);
 
@@ -270,7 +270,8 @@
         notificationRowBinder.setNotificationClicker(mock(NotificationClicker.class));
         mEntryManager.setRowBinder(notificationRowBinder);
 
-        setUserSentiment(mEntry.key, NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
+        setUserSentiment(
+                mEntry.getKey(), NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
     }
 
     @Test
@@ -317,7 +318,8 @@
 
         mEntryManager.getNotificationData().add(mEntry);
 
-        setUserSentiment(mEntry.key, NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+        setUserSentiment(
+                mEntry.getKey(), NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
 
         mEntryManager.updateNotification(mSbn, mRankingMap);
         TestableLooper.get(this).processMessages(1);
@@ -341,7 +343,7 @@
         TestableLooper.get(this).processAllMessages();
 
         NotificationData notifData = mock(NotificationData.class);
-        when(notifData.get(mEntry.key)).thenReturn(mEntry);
+        when(notifData.get(mEntry.getKey())).thenReturn(mEntry);
 
         mEntryManager.setNotificationData(notifData);
 
@@ -413,7 +415,7 @@
         mEntry.setRow(mRow);
         mEntry.setInflationTask(mAsyncInflationTask);
         mEntryManager.getNotificationData().add(mEntry);
-        setSmartActions(mEntry.key, new ArrayList<>(Arrays.asList(createAction())));
+        setSmartActions(mEntry.getKey(), new ArrayList<>(Arrays.asList(createAction())));
 
         mEntryManager.updateNotificationRanking(mRankingMap);
         verify(mRow).setEntry(eq(mEntry));
@@ -429,7 +431,7 @@
 
         mEntry.setRow(mRow);
         mEntryManager.getNotificationData().add(mEntry);
-        setSmartActions(mEntry.key, null);
+        setSmartActions(mEntry.getKey(), null);
 
         mEntryManager.updateNotificationRanking(mRankingMap);
         verify(mRow, never()).setEntry(eq(mEntry));
@@ -443,7 +445,7 @@
 
         mEntry.setRow(null);
         mEntryManager.getNotificationData().add(mEntry);
-        setSmartActions(mEntry.key, new ArrayList<>(Arrays.asList(createAction())));
+        setSmartActions(mEntry.getKey(), new ArrayList<>(Arrays.asList(createAction())));
 
         mEntryManager.updateNotificationRanking(mRankingMap);
         verify(mRow, never()).setEntry(eq(mEntry));
@@ -457,8 +459,8 @@
         when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
 
         mEntry.setRow(null);
-        mEntryManager.mPendingNotifications.put(mEntry.key, mEntry);
-        setSmartActions(mEntry.key, new ArrayList<>(Arrays.asList(createAction())));
+        mEntryManager.mPendingNotifications.put(mEntry.getKey(), mEntry);
+        setSmartActions(mEntry.getKey(), new ArrayList<>(Arrays.asList(createAction())));
 
         mEntryManager.updateNotificationRanking(mRankingMap);
         verify(mRow, never()).setEntry(eq(mEntry));
@@ -478,7 +480,7 @@
         mEntryManager.addNotificationLifetimeExtender(extender);
 
         // WHEN the notification is removed
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
         // THEN the extender is asked to manage the lifetime
         verify(extender).setShouldManageLifetime(mEntry, true);
@@ -494,12 +496,12 @@
         mEntryManager.getNotificationData().add(mEntry);
         final FakeNotificationLifetimeExtender extender = new FakeNotificationLifetimeExtender();
         mEntryManager.addNotificationLifetimeExtender(extender);
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
-        assertTrue(extender.isManaging(mEntry.key));
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
+        assertTrue(extender.isManaging(mEntry.getKey()));
 
         // WHEN the extender finishes its extension
         extender.setExtendLifetimes(false);
-        extender.getCallback().onSafeToRemove(mEntry.key);
+        extender.getCallback().onSafeToRemove(mEntry.getKey());
 
         // THEN the notification is removed
         assertNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
@@ -514,10 +516,10 @@
         NotificationLifetimeExtender extender = mock(NotificationLifetimeExtender.class);
         when(extender.shouldExtendLifetime(mEntry)).thenReturn(true);
         mEntryManager.addNotificationLifetimeExtender(extender);
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
         // WHEN the notification is updated
-        mEntryManager.updateNotification(mEntry.notification, mRankingMap);
+        mEntryManager.updateNotification(mEntry.getSbn(), mRankingMap);
 
         // THEN the lifetime extension is canceled
         verify(extender).setShouldManageLifetime(mEntry, false);
@@ -539,13 +541,13 @@
         mEntryManager.addNotificationLifetimeExtender(extender2);
 
         // GIVEN a notification was lifetime-extended and extender2 is managing it
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
         verify(extender1, never()).setShouldManageLifetime(mEntry, true);
         verify(extender2).setShouldManageLifetime(mEntry, true);
 
         // WHEN the extender1 changes its mind and wants to extend the lifetime of the notif
         when(extender1.shouldExtendLifetime(mEntry)).thenReturn(true);
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
         // THEN extender2 stops managing the notif and extender1 starts managing it
         verify(extender1).setShouldManageLifetime(mEntry, true);
@@ -569,14 +571,14 @@
         mEntryManager.getNotificationData().add(mEntry);
 
         // GIVEN interceptor that intercepts that entry
-        when(mRemoveInterceptor.onNotificationRemoveRequested(eq(mEntry.key), anyInt()))
+        when(mRemoveInterceptor.onNotificationRemoveRequested(eq(mEntry.getKey()), anyInt()))
                 .thenReturn(true);
 
         // WHEN the notification is removed
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
         // THEN the interceptor intercepts & the entry is not removed & no listeners are called
-        assertNotNull(mEntryManager.getNotificationData().get(mEntry.key));
+        assertNotNull(mEntryManager.getNotificationData().get(mEntry.getKey()));
         verify(mEntryListener, never()).onEntryRemoved(eq(mEntry),
                 any(NotificationVisibility.class), anyBoolean());
     }
@@ -588,14 +590,14 @@
         mEntryManager.getNotificationData().add(mEntry);
 
         // GIVEN interceptor that doesn't intercept
-        when(mRemoveInterceptor.onNotificationRemoveRequested(eq(mEntry.key), anyInt()))
+        when(mRemoveInterceptor.onNotificationRemoveRequested(eq(mEntry.getKey()), anyInt()))
                 .thenReturn(false);
 
         // WHEN the notification is removed
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
         // THEN the interceptor intercepts & the entry is not removed & no listeners are called
-        assertNull(mEntryManager.getNotificationData().get(mEntry.key));
+        assertNull(mEntryManager.getNotificationData().get(mEntry.getKey()));
         verify(mEntryListener, atLeastOnce()).onEntryRemoved(eq(mEntry),
                 any(NotificationVisibility.class), anyBoolean());
     }
@@ -626,17 +628,17 @@
         public void setShouldManageLifetime(
                 @NonNull NotificationEntry entry,
                 boolean shouldManage) {
-            final boolean hasEntry = mManagedNotifs.contains(entry.key);
+            final boolean hasEntry = mManagedNotifs.contains(entry.getKey());
             if (shouldManage) {
                 if (hasEntry) {
-                    throw new RuntimeException("Already managing this entry: " + entry.key);
+                    throw new RuntimeException("Already managing this entry: " + entry.getKey());
                 }
-                mManagedNotifs.add(entry.key);
+                mManagedNotifs.add(entry.getKey());
             } else {
                 if (!hasEntry) {
-                    throw new RuntimeException("Not managing this entry: " + entry.key);
+                    throw new RuntimeException("Not managing this entry: " + entry.getKey());
                 }
-                mManagedNotifs.remove(entry.key);
+                mManagedNotifs.remove(entry.getKey());
             }
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
index 45e1721..d85f275 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
@@ -142,7 +142,7 @@
     public void testSuppressSystemAlertNotification() {
         when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
         when(mFsc.isSystemAlertNotification(any())).thenReturn(true);
-        StatusBarNotification sbn = mRow.getEntry().notification;
+        StatusBarNotification sbn = mRow.getEntry().getSbn();
         Bundle bundle = new Bundle();
         bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[]{"something"});
         sbn.getNotification().extras = bundle;
@@ -152,7 +152,7 @@
 
     @Test
     public void testDoNotSuppressSystemAlertNotification() {
-        StatusBarNotification sbn = mRow.getEntry().notification;
+        StatusBarNotification sbn = mRow.getEntry().getSbn();
         Bundle bundle = new Bundle();
         bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[]{"something"});
         sbn.getNotification().extras = bundle;
@@ -180,7 +180,7 @@
         // missing extra
         assertFalse(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
 
-        StatusBarNotification sbn = mRow.getEntry().notification;
+        StatusBarNotification sbn = mRow.getEntry().getSbn();
         Bundle bundle = new Bundle();
         bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[]{});
         sbn.getNotification().extras = bundle;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
index 170c661..9202c51 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
@@ -109,7 +109,7 @@
         final NotificationEntry entry = buildEntry();
         mEntryListener.onEntryRemoved(
                 entry,
-                NotificationVisibility.obtain(entry.key, 0, 0, true),
+                NotificationVisibility.obtain(entry.getKey(), 0, 0, true),
                 false);
         verify(mListContainer).cleanUpViewStateForEntry(entry);
     }
@@ -126,13 +126,13 @@
         final NotificationEntry entry = buildEntry();
         mNotificationData.add(entry);
         when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
-                .thenReturn(entry.key);
+                .thenReturn(entry.getKey());
 
         // WHEN we are notified of a new app op
         mController.updateNotificationsForAppOp(
                 AppOpsManager.OP_CAMERA,
-                entry.notification.getUid(),
-                entry.notification.getPackageName(),
+                entry.getSbn().getUid(),
+                entry.getSbn().getPackageName(),
                 true);
 
         // THEN the app op is added to the entry
@@ -165,10 +165,10 @@
         expected.add(235);
         expected.add(1);
         when(mForegroundServiceController.getStandardLayoutKey(
-                entry.notification.getUserId(),
-                entry.notification.getPackageName())).thenReturn(entry.key);
-        when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
-                entry.notification.getPackageName())).thenReturn(expected);
+                entry.getSbn().getUserId(),
+                entry.getSbn().getPackageName())).thenReturn(entry.getKey());
+        when(mForegroundServiceController.getAppOps(entry.getSbn().getUserId(),
+                entry.getSbn().getPackageName())).thenReturn(expected);
 
         // WHEN the notification is added
         mEntryListener.onBeforeNotificationAdded(entry);
@@ -187,10 +187,10 @@
 
         mNotificationData.add(entry);
         when(mForegroundServiceController.getStandardLayoutKey(
-                entry.notification.getUserId(),
-                entry.notification.getPackageName())).thenReturn(entry.key);
-        when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
-                entry.notification.getPackageName())).thenReturn(null);
+                entry.getSbn().getUserId(),
+                entry.getSbn().getPackageName())).thenReturn(entry.getKey());
+        when(mForegroundServiceController.getAppOps(entry.getSbn().getUserId(),
+                entry.getSbn().getPackageName())).thenReturn(null);
 
         // WHEN the notification is added
         mEntryListener.onBeforeNotificationAdded(entry);
@@ -208,11 +208,11 @@
         ops.add(3);
         ops.add(235);
         ops.add(1);
-        when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
-                entry.notification.getPackageName())).thenReturn(ops);
+        when(mForegroundServiceController.getAppOps(entry.getSbn().getUserId(),
+                entry.getSbn().getPackageName())).thenReturn(ops);
         when(mForegroundServiceController.getStandardLayoutKey(
-                entry.notification.getUserId(),
-                entry.notification.getPackageName())).thenReturn("something else");
+                entry.getSbn().getUserId(),
+                entry.getSbn().getPackageName())).thenReturn("something else");
 
         // WHEN the notification is added
         mEntryListener.onBeforeNotificationAdded(entry);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
new file mode 100644
index 0000000..e1beb34
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -0,0 +1,625 @@
+/*
+ * 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.statusbar.notification.collection;
+
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_CLICK;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_UNKNOWN;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.annotation.Nullable;
+import android.os.RemoteException;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
+import android.service.notification.NotificationStats;
+import android.service.notification.StatusBarNotification;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.util.ArrayMap;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationEntryBuilder;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationListener.NotifServiceListener;
+import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+import com.android.systemui.util.Assert;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
+import java.util.Arrays;
+import java.util.Map;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class NotifCollectionTest extends SysuiTestCase {
+
+    @Mock private IStatusBarService mStatusBarService;
+    @Mock private NotificationListener mListenerService;
+    @Spy private RecordingCollectionListener mCollectionListener;
+
+    @Spy private RecordingLifetimeExtender mExtender1 = new RecordingLifetimeExtender("Extender1");
+    @Spy private RecordingLifetimeExtender mExtender2 = new RecordingLifetimeExtender("Extender2");
+    @Spy private RecordingLifetimeExtender mExtender3 = new RecordingLifetimeExtender("Extender3");
+
+    @Captor private ArgumentCaptor<NotifServiceListener> mListenerCaptor;
+    @Captor private ArgumentCaptor<NotificationEntry> mEntryCaptor;
+
+    private NotifCollection mCollection;
+    private NotifServiceListener mServiceListener;
+
+    private NoManSimulator mNoMan;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+
+        mCollection = new NotifCollection(mStatusBarService);
+        mCollection.attach(mListenerService);
+        mCollection.addCollectionListener(mCollectionListener);
+
+        // Capture the listener object that the collection registers with the listener service so
+        // we can simulate listener service events in tests below
+        verify(mListenerService).setDownstreamListener(mListenerCaptor.capture());
+        mServiceListener = checkNotNull(mListenerCaptor.getValue());
+
+        mNoMan = new NoManSimulator(mServiceListener);
+    }
+
+    @Test
+    public void testEventDispatchedWhenNotifPosted() {
+        // WHEN a notification is posted
+        PostedNotif notif1 = mNoMan.postNotif(
+                buildNotif(TEST_PACKAGE, 3)
+                        .setRank(4747));
+
+        // THEN the listener is notified
+        verify(mCollectionListener).onEntryAdded(mEntryCaptor.capture());
+
+        NotificationEntry entry = mEntryCaptor.getValue();
+        assertEquals(notif1.key, entry.getKey());
+        assertEquals(notif1.sbn, entry.getSbn());
+        assertEquals(notif1.ranking, entry.getRanking());
+    }
+
+    @Test
+    public void testEventDispatchedWhenNotifUpdated() {
+        // GIVEN a collection with one notif
+        mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
+                .setRank(4747));
+
+        // WHEN the notif is reposted
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
+                .setRank(89));
+
+        // THEN the listener is notified
+        verify(mCollectionListener).onEntryUpdated(mEntryCaptor.capture());
+
+        NotificationEntry entry = mEntryCaptor.getValue();
+        assertEquals(notif2.key, entry.getKey());
+        assertEquals(notif2.sbn, entry.getSbn());
+        assertEquals(notif2.ranking, entry.getRanking());
+    }
+
+    @Test
+    public void testEventDispatchedWhenNotifRemoved() {
+        // GIVEN a collection with one notif
+        mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3));
+        clearInvocations(mCollectionListener);
+
+        PostedNotif notif = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        NotificationEntry entry = mCollectionListener.getEntry(notif.key);
+        clearInvocations(mCollectionListener);
+
+        // WHEN a notif is retracted
+        mNoMan.retractNotif(notif.sbn, REASON_APP_CANCEL);
+
+        // THEN the listener is notified
+        verify(mCollectionListener).onEntryRemoved(entry, REASON_APP_CANCEL, false);
+        assertEquals(notif.sbn, entry.getSbn());
+        assertEquals(notif.ranking, entry.getRanking());
+    }
+
+    @Test
+    public void testRankingsAreUpdatedForOtherNotifs() {
+        // GIVEN a collection with one notif
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
+                .setRank(47));
+        NotificationEntry entry1 = mCollectionListener.getEntry(notif1.key);
+
+        // WHEN a new notif is posted, triggering a rerank
+        mNoMan.setRanking(notif1.sbn.getKey(), new RankingBuilder(notif1.ranking)
+                .setRank(56)
+                .build());
+        mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 77));
+
+        // THEN the ranking is updated on the first entry
+        assertEquals(56, entry1.getRanking().getRank());
+    }
+
+    @Test
+    public void testRankingUpdateIsProperlyIssuedToEveryone() {
+        // GIVEN a collection with a couple notifs
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
+                .setRank(3));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 8)
+                .setRank(2));
+        PostedNotif notif3 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 77)
+                .setRank(1));
+
+        NotificationEntry entry1 = mCollectionListener.getEntry(notif1.key);
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+        NotificationEntry entry3 = mCollectionListener.getEntry(notif3.key);
+
+        // WHEN a ranking update is delivered
+        Ranking newRanking1 = new RankingBuilder(notif1.ranking)
+                .setRank(4)
+                .setExplanation("Foo bar")
+                .build();
+        Ranking newRanking2 = new RankingBuilder(notif2.ranking)
+                .setRank(5)
+                .setExplanation("baz buzz")
+                .build();
+        Ranking newRanking3 = new RankingBuilder(notif3.ranking)
+                .setRank(6)
+                .setExplanation("Penguin pizza")
+                .build();
+
+        mNoMan.setRanking(notif1.sbn.getKey(), newRanking1);
+        mNoMan.setRanking(notif2.sbn.getKey(), newRanking2);
+        mNoMan.setRanking(notif3.sbn.getKey(), newRanking3);
+        mNoMan.issueRankingUpdate();
+
+        // THEN all of the NotifEntries have their rankings properly updated
+        assertEquals(newRanking1, entry1.getRanking());
+        assertEquals(newRanking2, entry2.getRanking());
+        assertEquals(newRanking3, entry3.getRanking());
+    }
+
+    @Test
+    public void testNotifEntriesAreNotPersistedAcrossRemovalAndReposting() {
+        // GIVEN a notification that has been posted
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3));
+        NotificationEntry entry1 = mCollectionListener.getEntry(notif1.key);
+
+        // WHEN the notification is retracted and then reposted
+        mNoMan.retractNotif(notif1.sbn, REASON_APP_CANCEL);
+        mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3));
+
+        // THEN the new NotificationEntry is a new object
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif1.key);
+        assertNotEquals(entry2, entry1);
+    }
+
+    @Test
+    public void testDismissNotification() throws RemoteException {
+        // GIVEN a collection with a couple notifications and a lifetime extender
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47, "myTag"));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88, "barTag"));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // WHEN a notification is manually dismissed
+        DismissedByUserStats stats = new DismissedByUserStats(
+                NotificationStats.DISMISSAL_SHADE,
+                NotificationStats.DISMISS_SENTIMENT_NEUTRAL,
+                NotificationVisibility.obtain(entry2.getKey(), 7, 2, true));
+
+        mCollection.dismissNotification(entry2, REASON_CLICK, stats);
+
+        // THEN we check for lifetime extension
+        verify(mExtender1).shouldExtendLifetime(entry2, REASON_CLICK);
+
+        // THEN we send the dismissal to system server
+        verify(mStatusBarService).onNotificationClear(
+                notif2.sbn.getPackageName(),
+                notif2.sbn.getTag(),
+                88,
+                notif2.sbn.getUser().getIdentifier(),
+                notif2.sbn.getKey(),
+                stats.dismissalSurface,
+                stats.dismissalSentiment,
+                stats.notificationVisibility);
+
+        // THEN we fire a remove event
+        verify(mCollectionListener).onEntryRemoved(entry2, REASON_CLICK, true);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testDismissingNonExistentNotificationThrows() {
+        // GIVEN a collection that originally had three notifs, but where one was dismissed
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        PostedNotif notif3 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 99));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+        mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
+
+        // WHEN we try to dismiss a notification that isn't present
+        mCollection.dismissNotification(
+                entry2,
+                REASON_CLICK,
+                new DismissedByUserStats(0, 0, NotificationVisibility.obtain("foo", 47, 3, true)));
+
+        // THEN an exception is thrown
+    }
+
+    @Test
+    public void testLifetimeExtendersAreQueriedWhenNotifRemoved() {
+        // GIVEN a couple notifications and a few lifetime extenders
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = true;
+
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // WHEN a notification is removed
+        mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
+
+        // THEN each extender is asked whether to extend, even if earlier ones return true
+        verify(mExtender1).shouldExtendLifetime(entry2, REASON_UNKNOWN);
+        verify(mExtender2).shouldExtendLifetime(entry2, REASON_UNKNOWN);
+        verify(mExtender3).shouldExtendLifetime(entry2, REASON_UNKNOWN);
+
+        // THEN the entry is not removed
+        assertTrue(mCollection.getNotifs().contains(entry2));
+
+        // THEN the entry properly records all extenders that returned true
+        assertEquals(Arrays.asList(mExtender1, mExtender2), entry2.mLifetimeExtenders);
+    }
+
+    @Test
+    public void testWhenLastLifetimeExtenderExpiresAllAreReQueried() {
+        // GIVEN a couple notifications and a few lifetime extenders
+        mExtender2.shouldExtendLifetime = true;
+
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // GIVEN a notification gets lifetime-extended by one of them
+        mNoMan.retractNotif(notif2.sbn, REASON_APP_CANCEL);
+        assertTrue(mCollection.getNotifs().contains(entry2));
+        clearInvocations(mExtender1, mExtender2, mExtender3);
+
+        // WHEN the last active extender expires (but new ones become active)
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = false;
+        mExtender3.shouldExtendLifetime = true;
+        mExtender2.callback.onEndLifetimeExtension(mExtender2, entry2);
+
+        // THEN each extender is re-queried
+        verify(mExtender1).shouldExtendLifetime(entry2, REASON_UNKNOWN);
+        verify(mExtender2).shouldExtendLifetime(entry2, REASON_UNKNOWN);
+        verify(mExtender3).shouldExtendLifetime(entry2, REASON_UNKNOWN);
+
+        // THEN the entry is not removed
+        assertTrue(mCollection.getNotifs().contains(entry2));
+
+        // THEN the entry properly records all extenders that returned true
+        assertEquals(Arrays.asList(mExtender1, mExtender3), entry2.mLifetimeExtenders);
+    }
+
+    @Test
+    public void testExtendersAreNotReQueriedUntilFinalActiveExtenderExpires() {
+        // GIVEN a couple notifications and a few lifetime extenders
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = true;
+
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // GIVEN a notification gets lifetime-extended by a couple of them
+        mNoMan.retractNotif(notif2.sbn, REASON_APP_CANCEL);
+        assertTrue(mCollection.getNotifs().contains(entry2));
+        clearInvocations(mExtender1, mExtender2, mExtender3);
+
+        // WHEN one (but not all) of the extenders expires
+        mExtender2.shouldExtendLifetime = false;
+        mExtender2.callback.onEndLifetimeExtension(mExtender2, entry2);
+
+        // THEN the entry is not removed
+        assertTrue(mCollection.getNotifs().contains(entry2));
+
+        // THEN we don't re-query the extenders
+        verify(mExtender1, never()).shouldExtendLifetime(eq(entry2), anyInt());
+        verify(mExtender2, never()).shouldExtendLifetime(eq(entry2), anyInt());
+        verify(mExtender3, never()).shouldExtendLifetime(eq(entry2), anyInt());
+
+        // THEN the entry properly records all extenders that returned true
+        assertEquals(Arrays.asList(mExtender1), entry2.mLifetimeExtenders);
+    }
+
+    @Test
+    public void testNotificationIsRemovedWhenAllLifetimeExtendersExpire() {
+        // GIVEN a couple notifications and a few lifetime extenders
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = true;
+
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // GIVEN a notification gets lifetime-extended by a couple of them
+        mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
+        assertTrue(mCollection.getNotifs().contains(entry2));
+        clearInvocations(mExtender1, mExtender2, mExtender3);
+
+        // WHEN all of the active extenders expire
+        mExtender2.shouldExtendLifetime = false;
+        mExtender2.callback.onEndLifetimeExtension(mExtender2, entry2);
+        mExtender1.shouldExtendLifetime = false;
+        mExtender1.callback.onEndLifetimeExtension(mExtender1, entry2);
+
+        // THEN the entry removed
+        assertFalse(mCollection.getNotifs().contains(entry2));
+        verify(mCollectionListener).onEntryRemoved(entry2, REASON_UNKNOWN, false);
+    }
+
+    @Test
+    public void testLifetimeExtensionIsCanceledWhenNotifIsUpdated() {
+        // GIVEN a few lifetime extenders and a couple notifications
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = true;
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // GIVEN a notification gets lifetime-extended by a couple of them
+        mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
+        assertTrue(mCollection.getNotifs().contains(entry2));
+        clearInvocations(mExtender1, mExtender2, mExtender3);
+
+        // WHEN the notification is reposted
+        mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+
+        // THEN all of the active lifetime extenders are canceled
+        verify(mExtender1).cancelLifetimeExtension(entry2);
+        verify(mExtender2).cancelLifetimeExtension(entry2);
+
+        // THEN the notification is still present
+        assertTrue(mCollection.getNotifs().contains(entry2));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testReentrantCallsToLifetimeExtendersThrow() {
+        // GIVEN a few lifetime extenders and a couple notifications
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = true;
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // GIVEN a notification gets lifetime-extended by a couple of them
+        mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
+        assertTrue(mCollection.getNotifs().contains(entry2));
+        clearInvocations(mExtender1, mExtender2, mExtender3);
+
+        // WHEN a lifetime extender makes a reentrant call during cancelLifetimeExtension()
+        mExtender2.onCancelLifetimeExtension = () -> {
+            mExtender2.callback.onEndLifetimeExtension(mExtender2, entry2);
+        };
+        // This triggers the call to cancelLifetimeExtension()
+        mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+
+        // THEN an exception is thrown
+    }
+
+    @Test
+    public void testRankingIsUpdatedWhenALifetimeExtendedNotifIsReposted() {
+        // GIVEN a few lifetime extenders and a couple notifications
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = true;
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // GIVEN a notification gets lifetime-extended by a couple of them
+        mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
+        assertTrue(mCollection.getNotifs().contains(entry2));
+        clearInvocations(mExtender1, mExtender2, mExtender3);
+
+        // WHEN the notification is reposted
+        PostedNotif notif2a = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88)
+                .setRank(4747)
+                .setExplanation("Some new explanation"));
+
+        // THEN the notification's ranking is properly updated
+        assertEquals(notif2a.ranking, entry2.getRanking());
+    }
+
+    private static NotificationEntryBuilder buildNotif(String pkg, int id, String tag) {
+        return new NotificationEntryBuilder()
+                .setPkg(pkg)
+                .setId(id)
+                .setTag(tag);
+    }
+
+    private static NotificationEntryBuilder buildNotif(String pkg, int id) {
+        return new NotificationEntryBuilder()
+                .setPkg(pkg)
+                .setId(id);
+    }
+
+    private static class NoManSimulator {
+        private final NotifServiceListener mListener;
+        private final Map<String, Ranking> mRankings = new ArrayMap<>();
+
+        private NoManSimulator(
+                NotifServiceListener listener) {
+            mListener = listener;
+        }
+
+        PostedNotif postNotif(NotificationEntryBuilder builder) {
+            NotificationEntry entry = builder.build();
+            mRankings.put(entry.getKey(), entry.getRanking());
+            mListener.onNotificationPosted(entry.getSbn(), buildRankingMap());
+            return new PostedNotif(entry.getSbn(), entry.getRanking());
+        }
+
+        void retractNotif(StatusBarNotification sbn, int reason) {
+            assertNotNull(mRankings.remove(sbn.getKey()));
+            mListener.onNotificationRemoved(sbn, buildRankingMap(), reason);
+        }
+
+        void issueRankingUpdate() {
+            mListener.onNotificationRankingUpdate(buildRankingMap());
+        }
+
+        void setRanking(String key, Ranking ranking) {
+            mRankings.put(key, ranking);
+        }
+
+        private RankingMap buildRankingMap() {
+            return new RankingMap(mRankings.values().toArray(new Ranking[0]));
+        }
+    }
+
+    private static class PostedNotif {
+        public final String key;
+        public final StatusBarNotification sbn;
+        public final Ranking ranking;
+
+        private PostedNotif(StatusBarNotification sbn,
+                Ranking ranking) {
+            this.key = sbn.getKey();
+            this.sbn = sbn;
+            this.ranking = ranking;
+        }
+    }
+
+    private static class RecordingCollectionListener implements NotifCollectionListener {
+        private final Map<String, NotificationEntry> mLastSeenEntries = new ArrayMap<>();
+
+        @Override
+        public void onEntryAdded(NotificationEntry entry) {
+            mLastSeenEntries.put(entry.getKey(), entry);
+        }
+
+        @Override
+        public void onEntryUpdated(NotificationEntry entry) {
+        }
+
+        @Override
+        public void onEntryRemoved(NotificationEntry entry, int reason, boolean removedByUser) {
+        }
+
+        public NotificationEntry getEntry(String key) {
+            if (!mLastSeenEntries.containsKey(key)) {
+                throw new RuntimeException("Key not found: " + key);
+            }
+            return mLastSeenEntries.get(key);
+        }
+    }
+
+    private static class RecordingLifetimeExtender implements NotifLifetimeExtender {
+        private final String mName;
+
+        public @Nullable OnEndLifetimeExtensionCallback callback;
+        public boolean shouldExtendLifetime = false;
+        public @Nullable Runnable onCancelLifetimeExtension;
+
+        private RecordingLifetimeExtender(String name) {
+            mName = name;
+        }
+
+        @Override
+        public String getName() {
+            return mName;
+        }
+
+        @Override
+        public void setCallback(OnEndLifetimeExtensionCallback callback) {
+            this.callback = callback;
+        }
+
+        @Override
+        public boolean shouldExtendLifetime(
+                NotificationEntry entry,
+                @CancellationReason int reason) {
+            return shouldExtendLifetime;
+        }
+
+        @Override
+        public void cancelLifetimeExtension(NotificationEntry entry) {
+            if (onCancelLifetimeExtension != null) {
+                onCancelLifetimeExtension.run();
+            }
+        }
+    }
+
+    private static final String TEST_PACKAGE = "com.android.test.collection";
+    private static final String TEST_PACKAGE2 = "com.android.test.collection2";
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
index 1be6f61..640984b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
@@ -153,7 +153,7 @@
     public void testChannelSetWhenAdded() {
         Bundle override = new Bundle();
         override.putParcelable(OVERRIDE_CHANNEL, NOTIFICATION_CHANNEL);
-        mNotificationData.rankingOverrides.put(mRow.getEntry().key, override);
+        mNotificationData.rankingOverrides.put(mRow.getEntry().getKey(), override);
         mNotificationData.add(mRow.getEntry());
         assertEquals(NOTIFICATION_CHANNEL, mRow.getEntry().getChannel());
     }
@@ -175,17 +175,17 @@
 
         for (int op : expectedOps) {
             mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
-                    NotificationTestHelper.PKG, mRow.getEntry().key, true);
+                    NotificationTestHelper.PKG, mRow.getEntry().getKey(), true);
             mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
-                    NotificationTestHelper.PKG, row2.getEntry().key, true);
+                    NotificationTestHelper.PKG, row2.getEntry().getKey(), true);
         }
         for (int op : expectedOps) {
-            assertTrue(mRow.getEntry().key + " doesn't have op " + op,
-                    mNotificationData.get(mRow.getEntry().key).mActiveAppOps.contains(op));
-            assertTrue(row2.getEntry().key + " doesn't have op " + op,
-                    mNotificationData.get(row2.getEntry().key).mActiveAppOps.contains(op));
-            assertFalse(diffPkg.getEntry().key + " has op " + op,
-                    mNotificationData.get(diffPkg.getEntry().key).mActiveAppOps.contains(op));
+            assertTrue(mRow.getEntry().getKey() + " doesn't have op " + op,
+                    mNotificationData.get(mRow.getEntry().getKey()).mActiveAppOps.contains(op));
+            assertTrue(row2.getEntry().getKey() + " doesn't have op " + op,
+                    mNotificationData.get(row2.getEntry().getKey()).mActiveAppOps.contains(op));
+            assertFalse(diffPkg.getEntry().getKey() + " has op " + op,
+                    mNotificationData.get(diffPkg.getEntry().getKey()).mActiveAppOps.contains(op));
         }
     }
 
@@ -202,22 +202,22 @@
 
         for (int op : expectedOps) {
             mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
-                    NotificationTestHelper.PKG, row2.getEntry().key, true);
+                    NotificationTestHelper.PKG, row2.getEntry().getKey(), true);
         }
 
         expectedOps.remove(OP_ACCEPT_HANDOVER);
         mNotificationData.updateAppOp(OP_ACCEPT_HANDOVER, NotificationTestHelper.UID,
-                NotificationTestHelper.PKG, row2.getEntry().key, false);
+                NotificationTestHelper.PKG, row2.getEntry().getKey(), false);
 
-        assertTrue(mRow.getEntry().key + " doesn't have op " + OP_CAMERA,
-                mNotificationData.get(mRow.getEntry().key).mActiveAppOps.contains(OP_CAMERA));
-        assertTrue(row2.getEntry().key + " doesn't have op " + OP_CAMERA,
-                mNotificationData.get(row2.getEntry().key).mActiveAppOps.contains(OP_CAMERA));
-        assertFalse(mRow.getEntry().key + " has op " + OP_ACCEPT_HANDOVER,
-                mNotificationData.get(mRow.getEntry().key)
+        assertTrue(mRow.getEntry().getKey() + " doesn't have op " + OP_CAMERA,
+                mNotificationData.get(mRow.getEntry().getKey()).mActiveAppOps.contains(OP_CAMERA));
+        assertTrue(row2.getEntry().getKey() + " doesn't have op " + OP_CAMERA,
+                mNotificationData.get(row2.getEntry().getKey()).mActiveAppOps.contains(OP_CAMERA));
+        assertFalse(mRow.getEntry().getKey() + " has op " + OP_ACCEPT_HANDOVER,
+                mNotificationData.get(mRow.getEntry().getKey())
                         .mActiveAppOps.contains(OP_ACCEPT_HANDOVER));
-        assertFalse(row2.getEntry().key + " has op " + OP_ACCEPT_HANDOVER,
-                mNotificationData.get(row2.getEntry().key)
+        assertFalse(row2.getEntry().getKey() + " has op " + OP_ACCEPT_HANDOVER,
+                mNotificationData.get(row2.getEntry().getKey())
                         .mActiveAppOps.contains(OP_ACCEPT_HANDOVER));
     }
 
@@ -230,9 +230,9 @@
         mNotificationData.add(row2.getEntry());
 
         when(mEnvironment.isNotificationForCurrentProfiles(
-                mRow.getEntry().notification)).thenReturn(false);
+                mRow.getEntry().getSbn())).thenReturn(false);
         when(mEnvironment.isNotificationForCurrentProfiles(
-                row2.getEntry().notification)).thenReturn(true);
+                row2.getEntry().getSbn())).thenReturn(true);
         ArrayList<NotificationEntry> result =
                 mNotificationData.getNotificationsForCurrentUser();
 
@@ -244,12 +244,12 @@
     public void testIsExemptFromDndVisualSuppression_foreground() {
         initStatusBarNotification(false);
 
-        mEntry.sbn().getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
+        mEntry.getSbn().getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
         mEntry.setRow(mRow);
         mNotificationData.add(mEntry);
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_VIS_EFFECTS, 255);
-        mNotificationData.rankingOverrides.put(mEntry.key, override);
+        mNotificationData.rankingOverrides.put(mEntry.getKey(), override);
 
         assertTrue(mEntry.isExemptFromDndVisualSuppression());
         assertFalse(mEntry.shouldSuppressAmbient());
@@ -258,7 +258,7 @@
     @Test
     public void testIsExemptFromDndVisualSuppression_media() {
         initStatusBarNotification(false);
-        Notification n = mEntry.sbn().getNotification();
+        Notification n = mEntry.getSbn().getNotification();
         Notification.Builder nb = Notification.Builder.recoverBuilder(mContext, n);
         nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class)));
         n = nb.build();
@@ -269,7 +269,7 @@
         mNotificationData.add(mEntry);
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_VIS_EFFECTS, 255);
-        mNotificationData.rankingOverrides.put(mEntry.key, override);
+        mNotificationData.rankingOverrides.put(mEntry.getKey(), override);
 
         assertTrue(mEntry.isExemptFromDndVisualSuppression());
         assertFalse(mEntry.shouldSuppressAmbient());
@@ -283,7 +283,7 @@
         mNotificationData.add(mEntry);
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_VIS_EFFECTS, 255);
-        mNotificationData.rankingOverrides.put(mEntry.key, override);
+        mNotificationData.rankingOverrides.put(mEntry.getKey(), override);
 
         assertTrue(mEntry.isExemptFromDndVisualSuppression());
         assertFalse(mEntry.shouldSuppressAmbient());
@@ -299,7 +299,7 @@
         entry.mIsSystemNotification = true;
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_VIS_EFFECTS, NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT);
-        mNotificationData.rankingOverrides.put(entry.key, override);
+        mNotificationData.rankingOverrides.put(entry.getKey(), override);
         mNotificationData.add(entry);
 
         modifySbn(entry)
@@ -511,7 +511,7 @@
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
         override.putInt(OVERRIDE_RANK, 1);
-        mNotificationData.rankingOverrides.put(a.key, override);
+        mNotificationData.rankingOverrides.put(a.getKey(), override);
 
         Notification bN = new Notification.Builder(mContext, "test")
                 .setStyle(new Notification.MessagingStyle(""))
@@ -530,7 +530,7 @@
         Bundle bOverride = new Bundle();
         bOverride.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
         bOverride.putInt(OVERRIDE_RANK, 2);
-        mNotificationData.rankingOverrides.put(b.key, bOverride);
+        mNotificationData.rankingOverrides.put(b.getKey(), bOverride);
 
         assertEquals(1, mNotificationData.mRankingComparator.compare(a, b));
     }
@@ -555,7 +555,7 @@
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
         override.putInt(OVERRIDE_RANK, 1);
-        mNotificationData.rankingOverrides.put(a.key, override);
+        mNotificationData.rankingOverrides.put(a.getKey(), override);
 
         Notification bN = new Notification.Builder(mContext, "test")
                 .setStyle(new Notification.MessagingStyle(""))
@@ -574,7 +574,7 @@
         Bundle bOverride = new Bundle();
         bOverride.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
         bOverride.putInt(OVERRIDE_RANK, 2);
-        mNotificationData.rankingOverrides.put(b.key, bOverride);
+        mNotificationData.rankingOverrides.put(b.getKey(), bOverride);
 
         assertEquals(-1, mNotificationData.mRankingComparator.compare(a, b));
     }
@@ -594,7 +594,7 @@
 
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_DEFAULT);
-        mNotificationData.rankingOverrides.put(entry.key(), override);
+        mNotificationData.rankingOverrides.put(entry.getKey(), override);
 
         entry.setRow(mRow);
         mNotificationData.add(entry);
@@ -618,7 +618,7 @@
 
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
-        mNotificationData.rankingOverrides.put(entry.key(), override);
+        mNotificationData.rankingOverrides.put(entry.getKey(), override);
 
         entry.setRow(mRow);
         mNotificationData.add(entry);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index 24cd056..47c17ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -113,7 +113,7 @@
     @Test
     public void testOnChildLocationsChangedReportsVisibilityChanged() throws Exception {
         NotificationVisibility[] newlyVisibleKeys = {
-                NotificationVisibility.obtain(mEntry.key, 0, 1, true)
+                NotificationVisibility.obtain(mEntry.getKey(), 0, 1, true)
         };
         NotificationVisibility[] noLongerVisibleKeys = {};
         doAnswer(invocation -> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 41fe173..c7877bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -487,13 +487,13 @@
         NotificationEntry entry = createTestNotificationRow().getEntry();
         mGutsManager.setShouldManageLifetime(entry, true /* shouldManage */);
 
-        assertTrue(entry.key.equals(mGutsManager.mKeyToRemoveOnGutsClosed));
+        assertTrue(entry.getKey().equals(mGutsManager.mKeyToRemoveOnGutsClosed));
     }
 
     @Test
     public void testSetShouldManageLifetime_setShouldNotManage() {
         NotificationEntry entry = createTestNotificationRow().getEntry();
-        mGutsManager.mKeyToRemoveOnGutsClosed = entry.key;
+        mGutsManager.mKeyToRemoveOnGutsClosed = entry.getKey();
         mGutsManager.setShouldManageLifetime(entry, false /* shouldManage */);
 
         assertNull(mGutsManager.mKeyToRemoveOnGutsClosed);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index ff9aae7..72bea56 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -76,6 +76,8 @@
     private Handler mHandler;
     @Mock
     private KeyguardBypassController mKeyguardBypassController;
+    @Mock
+    private DozeParameters mDozeParameters;
     private BiometricUnlockController mBiometricUnlockController;
 
     @Before
@@ -92,7 +94,8 @@
                 mStatusBarWindowController);
         mBiometricUnlockController = new BiometricUnlockController(mContext, mDozeScrimController,
                 mKeyguardViewMediator, mScrimController, mStatusBar, mKeyguardStateController,
-                mHandler, mUpdateMonitor, 0 /* wakeUpDelay */, mKeyguardBypassController);
+                mHandler, mUpdateMonitor, 0 /* wakeUpDelay */, mKeyguardBypassController,
+                mDozeParameters);
         mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DoubleTapHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DoubleTapHelperTest.java
new file mode 100644
index 0000000..df1233a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DoubleTapHelperTest.java
@@ -0,0 +1,369 @@
+/*
+ * 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.statusbar.phone;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyLong;
+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.content.res.Resources;
+import android.os.SystemClock;
+import android.testing.AndroidTestingRunner;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+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)
+public class DoubleTapHelperTest extends SysuiTestCase {
+
+    private DoubleTapHelper mDoubleTapHelper;
+    private int mTouchSlop;
+    private int mDoubleTouchSlop;
+    @Mock private View mView;
+    @Mock private DoubleTapHelper.ActivationListener mActivationListener;
+    @Mock private DoubleTapHelper.DoubleTapListener mDoubleTapListener;
+    @Mock private DoubleTapHelper.SlideBackListener mSlideBackListener;
+    @Mock private DoubleTapHelper.DoubleTapLogListener mDoubleTapLogListener;
+    @Mock private Resources mResources;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+        // The double tap slop has to be less than the regular slop, otherwise it has no effect.
+        mDoubleTouchSlop = mTouchSlop - 1;
+        when(mView.getContext()).thenReturn(mContext);
+        when(mView.getResources()).thenReturn(mResources);
+        when(mResources.getDimension(R.dimen.double_tap_slop))
+                .thenReturn((float) mDoubleTouchSlop);
+
+        mDoubleTapHelper = new DoubleTapHelper(mView,
+                                               mActivationListener,
+                                               mDoubleTapListener,
+                                               mSlideBackListener, mDoubleTapLogListener);
+    }
+
+    @Test
+    public void testDoubleTap_success() {
+        long downtimeA = SystemClock.uptimeMillis();
+        long downtimeB = downtimeA + 100;
+
+        MotionEvent evDownA = MotionEvent.obtain(downtimeA,
+                                                 downtimeA,
+                                                 MotionEvent.ACTION_DOWN,
+                                                 1,
+                                                 1,
+                                                 0);
+        MotionEvent evUpA = MotionEvent.obtain(downtimeA,
+                                               downtimeA + 1,
+                                               MotionEvent.ACTION_UP,
+                                               1,
+                                               1,
+                                               0);
+        MotionEvent evDownB = MotionEvent.obtain(downtimeB,
+                                                 downtimeB,
+                                                 MotionEvent.ACTION_DOWN,
+                                                 1,
+                                                 1,
+                                                 0);
+        MotionEvent evUpB = MotionEvent.obtain(downtimeB,
+                                               downtimeB + 1,
+                                               MotionEvent.ACTION_UP,
+                                               1,
+                                               1,
+                                               0);
+
+        mDoubleTapHelper.onTouchEvent(evDownA);
+        mDoubleTapHelper.onTouchEvent(evUpA);
+        verify(mActivationListener).onActiveChanged(true);
+        verify(mView).postDelayed(any(Runnable.class), anyLong());
+        verify(mDoubleTapLogListener, never()).onDoubleTapLog(anyBoolean(), anyFloat(), anyFloat());
+        verify(mDoubleTapListener, never()).onDoubleTap();
+
+        mDoubleTapHelper.onTouchEvent(evDownB);
+        mDoubleTapHelper.onTouchEvent(evUpB);
+        verify(mDoubleTapLogListener).onDoubleTapLog(true, 0, 0);
+        verify(mDoubleTapListener).onDoubleTap();
+
+        evDownA.recycle();
+        evUpA.recycle();
+        evDownB.recycle();
+        evUpB.recycle();
+    }
+
+    @Test
+    public void testSingleTap_timeout() {
+        long downtimeA = SystemClock.uptimeMillis();
+
+        MotionEvent evDownA = MotionEvent.obtain(downtimeA,
+                                                 downtimeA,
+                                                 MotionEvent.ACTION_DOWN,
+                                                 1,
+                                                 1,
+                                                 0);
+        MotionEvent evUpA = MotionEvent.obtain(downtimeA,
+                                               downtimeA + 1,
+                                               MotionEvent.ACTION_UP,
+                                               1,
+                                               1,
+                                               0);
+
+        ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+        mDoubleTapHelper.onTouchEvent(evDownA);
+        mDoubleTapHelper.onTouchEvent(evUpA);
+        verify(mActivationListener).onActiveChanged(true);
+        verify(mView).postDelayed(runnableCaptor.capture(), anyLong());
+        runnableCaptor.getValue().run();
+        verify(mActivationListener).onActiveChanged(true);
+
+        evDownA.recycle();
+        evUpA.recycle();
+    }
+
+    @Test
+    public void testSingleTap_slop() {
+        long downtimeA = SystemClock.uptimeMillis();
+
+        MotionEvent evDownA = MotionEvent.obtain(downtimeA,
+                                                 downtimeA,
+                                                 MotionEvent.ACTION_DOWN,
+                                                 1,
+                                                 1,
+                                                 0);
+        MotionEvent evUpA = MotionEvent.obtain(downtimeA,
+                                               downtimeA + 1,
+                                               MotionEvent.ACTION_UP,
+                                               1 + mTouchSlop,
+                                               1,
+                                               0);
+
+        ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+        mDoubleTapHelper.onTouchEvent(evDownA);
+        mDoubleTapHelper.onTouchEvent(evUpA);
+        verify(mActivationListener, never()).onActiveChanged(true);
+        verify(mDoubleTapListener, never()).onDoubleTap();
+
+        evDownA.recycle();
+        evUpA.recycle();
+    }
+
+    @Test
+    public void testDoubleTap_slop() {
+        long downtimeA = SystemClock.uptimeMillis();
+        long downtimeB = downtimeA + 100;
+
+        MotionEvent evDownA = MotionEvent.obtain(downtimeA,
+                                                 downtimeA,
+                                                 MotionEvent.ACTION_DOWN,
+                                                 1,
+                                                 1,
+                                                 0);
+        MotionEvent evUpA = MotionEvent.obtain(downtimeA,
+                                               downtimeA + 1,
+                                               MotionEvent.ACTION_UP,
+                                               1,
+                                               1,
+                                               0);
+        MotionEvent evDownB = MotionEvent.obtain(downtimeB,
+                                                 downtimeB,
+                                                 MotionEvent.ACTION_DOWN,
+                                                 1,
+                                                 1,
+                                                 0);
+        MotionEvent evUpB = MotionEvent.obtain(downtimeB,
+                                               downtimeB + 1,
+                                               MotionEvent.ACTION_UP,
+                                               1,
+                                               1 + mDoubleTouchSlop,
+                                               0);
+
+        mDoubleTapHelper.onTouchEvent(evDownA);
+        mDoubleTapHelper.onTouchEvent(evUpA);
+        verify(mActivationListener).onActiveChanged(true);
+        verify(mView).postDelayed(any(Runnable.class), anyLong());
+
+        mDoubleTapHelper.onTouchEvent(evDownB);
+        mDoubleTapHelper.onTouchEvent(evUpB);
+        verify(mDoubleTapLogListener).onDoubleTapLog(false, 0, mDoubleTouchSlop);
+        verify(mActivationListener).onActiveChanged(false);
+        verify(mDoubleTapListener, never()).onDoubleTap();
+
+        evDownA.recycle();
+        evUpA.recycle();
+        evDownB.recycle();
+        evUpB.recycle();
+    }
+
+    @Test
+    public void testSlideBack() {
+        long downtimeA = SystemClock.uptimeMillis();
+        long downtimeB = downtimeA + 100;
+
+        MotionEvent evDownA = MotionEvent.obtain(downtimeA,
+                                                 downtimeA,
+                                                 MotionEvent.ACTION_DOWN,
+                                                 1,
+                                                 1,
+                                                 0);
+        MotionEvent evUpA = MotionEvent.obtain(downtimeA,
+                                               downtimeA + 1,
+                                               MotionEvent.ACTION_UP,
+                                               1,
+                                               1,
+                                               0);
+        MotionEvent evDownB = MotionEvent.obtain(downtimeB,
+                                                 downtimeB,
+                                                 MotionEvent.ACTION_DOWN,
+                                                 1,
+                                                 1,
+                                                 0);
+        MotionEvent evUpB = MotionEvent.obtain(downtimeB,
+                                               downtimeB + 1,
+                                               MotionEvent.ACTION_UP,
+                                               1,
+                                               1,
+                                               0);
+
+        when(mSlideBackListener.onSlideBack()).thenReturn(true);
+
+        mDoubleTapHelper.onTouchEvent(evDownA);
+        mDoubleTapHelper.onTouchEvent(evUpA);
+        verify(mActivationListener, never()).onActiveChanged(true);
+        verify(mActivationListener, never()).onActiveChanged(false);
+        verify(mDoubleTapListener, never()).onDoubleTap();
+        mDoubleTapHelper.onTouchEvent(evDownB);
+        mDoubleTapHelper.onTouchEvent(evUpB);
+        verify(mActivationListener, never()).onActiveChanged(true);
+        verify(mActivationListener, never()).onActiveChanged(false);
+        verify(mDoubleTapListener, never()).onDoubleTap();
+
+        evDownA.recycle();
+        evUpA.recycle();
+        evDownB.recycle();
+        evUpB.recycle();
+    }
+
+
+    @Test
+    public void testMoreThanTwoTaps() {
+        long downtimeA = SystemClock.uptimeMillis();
+        long downtimeB = downtimeA + 100;
+        long downtimeC = downtimeB + 100;
+        long downtimeD = downtimeC + 100;
+
+        MotionEvent evDownA = MotionEvent.obtain(downtimeA,
+                                                 downtimeA,
+                                                 MotionEvent.ACTION_DOWN,
+                                                 1,
+                                                 1,
+                                                 0);
+        MotionEvent evUpA = MotionEvent.obtain(downtimeA,
+                                               downtimeA + 1,
+                                               MotionEvent.ACTION_UP,
+                                               1,
+                                               1,
+                                               0);
+        MotionEvent evDownB = MotionEvent.obtain(downtimeB,
+                                                 downtimeB,
+                                                 MotionEvent.ACTION_DOWN,
+                                                 1,
+                                                 1,
+                                                 0);
+        MotionEvent evUpB = MotionEvent.obtain(downtimeB,
+                                               downtimeB + 1,
+                                               MotionEvent.ACTION_UP,
+                                               1,
+                                               1,
+                                               0);
+        MotionEvent evDownC = MotionEvent.obtain(downtimeC,
+                                                 downtimeC,
+                                                 MotionEvent.ACTION_DOWN,
+                                                 1,
+                                                 1,
+                                                 0);
+        MotionEvent evUpC = MotionEvent.obtain(downtimeC,
+                                               downtimeC + 1,
+                                               MotionEvent.ACTION_UP,
+                                               1,
+                                               1,
+                                               0);
+        MotionEvent evDownD = MotionEvent.obtain(downtimeD,
+                                                 downtimeD,
+                                                 MotionEvent.ACTION_DOWN,
+                                                 1,
+                                                 1,
+                                                 0);
+        MotionEvent evUpD = MotionEvent.obtain(downtimeD,
+                                               downtimeD + 1,
+                                               MotionEvent.ACTION_UP,
+                                               1,
+                                               1,
+                                               0);
+
+        mDoubleTapHelper.onTouchEvent(evDownA);
+        mDoubleTapHelper.onTouchEvent(evUpA);
+        verify(mActivationListener).onActiveChanged(true);
+        verify(mView).postDelayed(any(Runnable.class), anyLong());
+        verify(mDoubleTapLogListener, never()).onDoubleTapLog(anyBoolean(), anyFloat(), anyFloat());
+        verify(mDoubleTapListener, never()).onDoubleTap();
+
+        mDoubleTapHelper.onTouchEvent(evDownB);
+        mDoubleTapHelper.onTouchEvent(evUpB);
+        verify(mDoubleTapLogListener).onDoubleTapLog(true, 0, 0);
+        verify(mDoubleTapListener).onDoubleTap();
+
+        reset(mView);
+        reset(mActivationListener);
+        reset(mDoubleTapLogListener);
+        reset(mDoubleTapListener);
+
+        mDoubleTapHelper.onTouchEvent(evDownC);
+        mDoubleTapHelper.onTouchEvent(evUpC);
+        verify(mActivationListener).onActiveChanged(true);
+        verify(mView).postDelayed(any(Runnable.class), anyLong());
+        verify(mDoubleTapLogListener, never()).onDoubleTapLog(anyBoolean(), anyFloat(), anyFloat());
+        verify(mDoubleTapListener, never()).onDoubleTap();
+
+        mDoubleTapHelper.onTouchEvent(evDownD);
+        mDoubleTapHelper.onTouchEvent(evUpD);
+        verify(mDoubleTapLogListener).onDoubleTapLog(true, 0, 0);
+        verify(mDoubleTapListener).onDoubleTap();
+
+        evDownA.recycle();
+        evUpA.recycle();
+        evDownB.recycle();
+        evUpB.recycle();
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
index 60050b1..debc840 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
@@ -17,68 +17,73 @@
 package com.android.systemui.statusbar.phone;
 
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 
-import android.content.Context;
+import android.content.res.Resources;
+import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.PowerManager;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.doze.AlwaysOnDisplayPolicy;
 import com.android.systemui.doze.DozeScreenState;
+import com.android.systemui.tuner.TunerService;
 
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class DozeParametersTest extends SysuiTestCase {
 
+    private DozeParameters mDozeParameters;
+
+    @Mock Resources mResources;
+    @Mock private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
+    @Mock private AlwaysOnDisplayPolicy mAlwaysOnDisplayPolicy;
+    @Mock private PowerManager mPowerManager;
+    @Mock private TunerService mTunerService;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mDozeParameters = new DozeParameters(
+            mResources,
+            mAmbientDisplayConfiguration,
+            mAlwaysOnDisplayPolicy,
+            mPowerManager,
+            mTunerService
+        );
+    }
     @Test
     public void test_setControlScreenOffAnimation_setsDozeAfterScreenOff_false() {
-        TestableDozeParameters dozeParameters = new TestableDozeParameters(getContext());
-        PowerManager mockedPowerManager = dozeParameters.getPowerManager();
-        dozeParameters.setControlScreenOffAnimation(true);
-        reset(mockedPowerManager);
-        dozeParameters.setControlScreenOffAnimation(false);
-        verify(mockedPowerManager).setDozeAfterScreenOff(eq(true));
+        mDozeParameters.setControlScreenOffAnimation(true);
+        reset(mPowerManager);
+        mDozeParameters.setControlScreenOffAnimation(false);
+        verify(mPowerManager).setDozeAfterScreenOff(eq(true));
     }
 
     @Test
     public void test_setControlScreenOffAnimation_setsDozeAfterScreenOff_true() {
-        TestableDozeParameters dozeParameters = new TestableDozeParameters(getContext());
-        PowerManager mockedPowerManager = dozeParameters.getPowerManager();
-        dozeParameters.setControlScreenOffAnimation(false);
-        reset(mockedPowerManager);
-        dozeParameters.setControlScreenOffAnimation(true);
-        verify(dozeParameters.getPowerManager()).setDozeAfterScreenOff(eq(false));
+        mDozeParameters.setControlScreenOffAnimation(false);
+        reset(mPowerManager);
+        mDozeParameters.setControlScreenOffAnimation(true);
+        verify(mPowerManager).setDozeAfterScreenOff(eq(false));
     }
 
     @Test
     public void test_getWallpaperAodDuration_when_shouldControlScreenOff() {
-        TestableDozeParameters dozeParameters = new TestableDozeParameters(getContext());
-        dozeParameters.setControlScreenOffAnimation(true);
-        Assert.assertEquals("wallpaper hides faster when controlling screen off",
-                dozeParameters.getWallpaperAodDuration(),
+        mDozeParameters.setControlScreenOffAnimation(true);
+        Assert.assertEquals(
+                "wallpaper hides faster when controlling screen off",
+                mDozeParameters.getWallpaperAodDuration(),
                 DozeScreenState.ENTER_DOZE_HIDE_WALLPAPER_DELAY);
     }
-
-    private class TestableDozeParameters extends DozeParameters {
-        private PowerManager mPowerManager;
-
-        TestableDozeParameters(Context context) {
-            super(context);
-            mPowerManager = mock(PowerManager.class);
-        }
-
-        @Override
-        protected PowerManager getPowerManager() {
-            return mPowerManager;
-        }
-    }
-
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
index 6fcf550..2068f7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -102,27 +102,27 @@
 
         mHeadsUpManager.snooze();
 
-        assertTrue(mHeadsUpManager.isSnoozed(mEntry.notification.getPackageName()));
+        assertTrue(mHeadsUpManager.isSnoozed(mEntry.getSbn().getPackageName()));
     }
 
     @Test
     public void testSwipedOutNotification() {
         mHeadsUpManager.showNotification(mEntry);
-        mHeadsUpManager.addSwipedOutNotification(mEntry.key);
+        mHeadsUpManager.addSwipedOutNotification(mEntry.getKey());
 
         // Remove should succeed because the notification is swiped out
-        mHeadsUpManager.removeNotification(mEntry.key, false /* releaseImmediately */);
+        mHeadsUpManager.removeNotification(mEntry.getKey(), false /* releaseImmediately */);
 
-        assertFalse(mHeadsUpManager.isAlerting(mEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(mEntry.getKey()));
     }
 
     @Test
     public void testCanRemoveImmediately_swipedOut() {
         mHeadsUpManager.showNotification(mEntry);
-        mHeadsUpManager.addSwipedOutNotification(mEntry.key);
+        mHeadsUpManager.addSwipedOutNotification(mEntry.getKey());
 
         // Notification is swiped so it can be immediately removed.
-        assertTrue(mHeadsUpManager.canRemoveImmediately(mEntry.key));
+        assertTrue(mHeadsUpManager.canRemoveImmediately(mEntry.getKey()));
     }
 
     @Test
@@ -135,7 +135,7 @@
         mHeadsUpManager.showNotification(laterEntry);
 
         // Notification is "behind" a higher priority notification so we can remove it immediately.
-        assertTrue(mHeadsUpManager.canRemoveImmediately(mEntry.key));
+        assertTrue(mHeadsUpManager.canRemoveImmediately(mEntry.getKey()));
     }
 
 
@@ -143,7 +143,7 @@
     public void testExtendHeadsUp() {
         mHeadsUpManager.showNotification(mEntry);
         Runnable pastNormalTimeRunnable =
-                () -> mLivesPastNormalTime = mHeadsUpManager.isAlerting(mEntry.key);
+                () -> mLivesPastNormalTime = mHeadsUpManager.isAlerting(mEntry.getKey());
         mTestHandler.postDelayed(pastNormalTimeRunnable,
                 TEST_AUTO_DISMISS_TIME + mHeadsUpManager.mExtensionTime / 2);
         mTestHandler.postDelayed(TEST_TIMEOUT_RUNNABLE, TEST_TIMEOUT_TIME);
@@ -155,6 +155,6 @@
 
         assertFalse("Test timed out", mTimedOut);
         assertTrue("Pulse was not extended", mLivesPastNormalTime);
-        assertFalse(mHeadsUpManager.isAlerting(mEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(mEntry.getKey()));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
index 2254234..5b54fba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
@@ -102,8 +102,8 @@
         mGroupManager.onEntryAdded(childEntry);
 
         // A suppressed summary should transfer its alert state to the child.
-        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.key));
-        assertTrue(mHeadsUpManager.isAlerting(childEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
+        assertTrue(mHeadsUpManager.isAlerting(childEntry.getKey()));
     }
 
     @Test
@@ -120,14 +120,14 @@
         mGroupManager.onEntryAdded(childEntry);
 
         // Add second child notification so that summary is no longer suppressed.
-        mPendingEntries.put(childEntry2.key, childEntry2);
+        mPendingEntries.put(childEntry2.getKey(), childEntry2);
         mNotificationEntryListener.onPendingEntryAdded(childEntry2);
         mGroupManager.onEntryAdded(childEntry2);
 
         // The alert state should transfer back to the summary as there is now more than one
         // child and the summary should no longer be suppressed.
-        assertTrue(mHeadsUpManager.isAlerting(summaryEntry.key));
-        assertFalse(mHeadsUpManager.isAlerting(childEntry.key));
+        assertTrue(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
+        assertFalse(mHeadsUpManager.isAlerting(childEntry.getKey()));
     }
 
     @Test
@@ -147,12 +147,12 @@
         mGroupAlertTransferHelper.onDozingChanged(true);
 
         // Add second child notification so that summary is no longer suppressed.
-        mPendingEntries.put(childEntry2.key, childEntry2);
+        mPendingEntries.put(childEntry2.getKey(), childEntry2);
         mNotificationEntryListener.onPendingEntryAdded(childEntry2);
         mGroupManager.onEntryAdded(childEntry2);
 
         // Dozing changed so no reason to re-alert summary.
-        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
     }
 
     @Test
@@ -168,8 +168,8 @@
 
         // Alert is immediately removed from summary, but we do not show child yet either as its
         // content is not inflated.
-        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.key));
-        assertFalse(mHeadsUpManager.isAlerting(childEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
+        assertFalse(mHeadsUpManager.isAlerting(childEntry.getKey()));
         assertTrue(mGroupAlertTransferHelper.isAlertTransferPending(childEntry));
     }
 
@@ -189,8 +189,8 @@
         mNotificationEntryListener.onEntryReinflated(childEntry);
 
         // Alert is immediately removed from summary, and we show child as its content is inflated.
-        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.key));
-        assertTrue(mHeadsUpManager.isAlerting(childEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
+        assertTrue(mHeadsUpManager.isAlerting(childEntry.getKey()));
     }
 
     @Test
@@ -209,7 +209,7 @@
         mGroupManager.onEntryAdded(childEntry);
 
         // Add second child notification so that summary is no longer suppressed.
-        mPendingEntries.put(childEntry2.key, childEntry2);
+        mPendingEntries.put(childEntry2.getKey(), childEntry2);
         mNotificationEntryListener.onPendingEntryAdded(childEntry2);
         mGroupManager.onEntryAdded(childEntry2);
 
@@ -220,7 +220,7 @@
 
         verify(childEntry.getRow(), times(1)).freeContentViewWhenSafe(mHeadsUpManager
             .getContentFlag());
-        assertFalse(mHeadsUpManager.isAlerting(childEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(childEntry.getKey()));
     }
 
     @Test
@@ -255,10 +255,10 @@
         mGroupManager.onEntryAdded(childEntry);
 
         // Notify that entry changed groups.
-        StatusBarNotification oldNotification = childEntry.notification;
-        StatusBarNotification newSbn = spy(childEntry.notification.clone());
+        StatusBarNotification oldNotification = childEntry.getSbn();
+        StatusBarNotification newSbn = spy(childEntry.getSbn().clone());
         doReturn("other_group").when(newSbn).getGroupKey();
-        childEntry.setNotification(newSbn);
+        childEntry.setSbn(newSbn);
         mGroupManager.onEntryUpdated(childEntry, oldNotification);
 
         assertFalse(mGroupAlertTransferHelper.isAlertTransferPending(childEntry));
@@ -278,10 +278,10 @@
         mGroupManager.onEntryAdded(childEntry);
 
         // Update that child to a summary.
-        StatusBarNotification oldNotification = childEntry.notification;
-        childEntry.setNotification(
+        StatusBarNotification oldNotification = childEntry.getSbn();
+        childEntry.setSbn(
                 mGroupTestHelper.createSummaryNotification(
-                        Notification.GROUP_ALERT_SUMMARY, 47).notification);
+                        Notification.GROUP_ALERT_SUMMARY, 47).getSbn());
         mGroupManager.onEntryUpdated(childEntry, oldNotification);
 
         assertFalse(mGroupAlertTransferHelper.isAlertTransferPending(childEntry));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java
index 493b74d..19ce1ea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java
@@ -75,7 +75,7 @@
         mGroupManager.onEntryAdded(summaryEntry);
         mGroupManager.onEntryAdded(childEntry);
 
-        assertTrue(mGroupManager.isOnlyChildInGroup(childEntry.notification));
+        assertTrue(mGroupManager.isOnlyChildInGroup(childEntry.getSbn()));
     }
 
     @Test
@@ -87,7 +87,7 @@
         mGroupManager.onEntryAdded(childEntry);
         mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification());
 
-        assertTrue(mGroupManager.isChildInGroupWithSummary(childEntry.notification));
+        assertTrue(mGroupManager.isChildInGroupWithSummary(childEntry.getSbn()));
     }
 
     @Test
@@ -99,8 +99,8 @@
         mGroupManager.onEntryAdded(childEntry);
         mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification());
 
-        assertTrue(mGroupManager.isSummaryOfGroup(summaryEntry.notification));
-        assertEquals(summaryEntry, mGroupManager.getGroupSummary(childEntry.notification));
+        assertTrue(mGroupManager.isSummaryOfGroup(summaryEntry.getSbn()));
+        assertEquals(summaryEntry, mGroupManager.getGroupSummary(childEntry.getSbn()));
     }
 
     @Test
@@ -113,7 +113,7 @@
 
         mGroupManager.onEntryRemoved(childEntry);
 
-        assertFalse(mGroupManager.isChildInGroupWithSummary(childEntry.notification));
+        assertFalse(mGroupManager.isChildInGroupWithSummary(childEntry.getSbn()));
     }
 
     @Test
@@ -126,8 +126,8 @@
 
         mGroupManager.onEntryRemoved(summaryEntry);
 
-        assertNull(mGroupManager.getGroupSummary(childEntry.notification));
-        assertFalse(mGroupManager.isSummaryOfGroup(summaryEntry.notification));
+        assertNull(mGroupManager.getGroupSummary(childEntry.getSbn()));
+        assertFalse(mGroupManager.isSummaryOfGroup(summaryEntry.getSbn()));
     }
 
     @Test
@@ -137,13 +137,13 @@
         mGroupManager.onEntryAdded(summaryEntry);
         mGroupManager.onEntryAdded(childEntry);
         mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification());
-        when(mHeadsUpManager.isAlerting(childEntry.key)).thenReturn(true);
+        when(mHeadsUpManager.isAlerting(childEntry.getKey())).thenReturn(true);
 
         mGroupManager.onHeadsUpStateChanged(childEntry, true);
 
         // Child entries that are heads upped should be considered separate groups visually even if
         // they are the same group logically
-        assertEquals(childEntry, mGroupManager.getGroupSummary(childEntry.notification));
-        assertEquals(summaryEntry, mGroupManager.getLogicalGroupSummary(childEntry.notification));
+        assertEquals(childEntry, mGroupManager.getGroupSummary(childEntry.getSbn()));
+        assertEquals(summaryEntry, mGroupManager.getLogicalGroupSummary(childEntry.getSbn()));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
index f1a7905..a49ae35 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
@@ -87,7 +87,7 @@
         ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
         entry.setRow(row);
         when(row.getEntry()).thenReturn(entry);
-        when(row.getStatusBarNotification()).thenReturn(entry.sbn());
+        when(row.getStatusBarNotification()).thenReturn(entry.getSbn());
         when(row.isInflationFlagSet(anyInt())).thenReturn(true);
         return entry;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 2c19037..cff6635 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -116,6 +116,7 @@
     private FalsingManager mFalsingManager;
     @Mock
     private KeyguardBypassController mKeyguardBypassController;
+    @Mock private DozeParameters mDozeParameters;
     private NotificationPanelView mNotificationPanelView;
 
     @Before
@@ -130,10 +131,11 @@
         mDependency.injectMockDependency(ConfigurationController.class);
         mDependency.injectMockDependency(ZenModeController.class);
         NotificationWakeUpCoordinator coordinator =
-                new NotificationWakeUpCoordinator(mContext,
+                new NotificationWakeUpCoordinator(
                         mock(HeadsUpManagerPhone.class),
                         new StatusBarStateControllerImpl(),
-                        mKeyguardBypassController);
+                        mKeyguardBypassController,
+                        mDozeParameters);
         PulseExpansionHandler expansionHandler = new PulseExpansionHandler(
                 mContext,
                 coordinator,
@@ -239,7 +241,8 @@
                             mock(NotifLog.class)),
                     mock(KeyguardStateController.class),
                     statusBarStateController,
-                    mock(DozeLog.class));
+                    mock(DozeLog.class),
+                    mDozeParameters);
             mNotificationStackScroller = mNotificationStackScrollLayout;
             mKeyguardStatusView = NotificationPanelViewTest.this.mKeyguardStatusView;
             mKeyguardStatusBar = NotificationPanelViewTest.this.mKeyguardStatusBar;
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 214e26a..f3ff7ec 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
@@ -133,6 +133,20 @@
     }
 
     @Test
+    public void transitionToOff() {
+        mScrimController.transitionTo(ScrimState.OFF);
+        mScrimController.finishAnimationsImmediately();
+
+        assertScrimAlpha(OPAQUE /* front */,
+                SEMI_TRANSPARENT /* back */,
+                TRANSPARENT /* bubble */);
+
+        assertScrimTint(true /* front */,
+                true /* behind */,
+                false /* bubble */);
+    }
+
+    @Test
     public void transitionToAod_withRegularWallpaper() {
         mScrimController.transitionTo(ScrimState.AOD);
         mScrimController.finishAnimationsImmediately();
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 210c9d6..c0c42ef 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
@@ -132,7 +132,7 @@
         TestableLooper.get(this).processAllMessages();
 
         assertFalse("The panel shouldn't allow heads up while disabled",
-                mStatusBar.canHeadsUp(entry, entry.sbn()));
+                mStatusBar.canHeadsUp(entry, entry.getSbn()));
     }
 
     @Test
@@ -149,7 +149,7 @@
         TestableLooper.get(this).processAllMessages();
 
         assertFalse("The panel shouldn't allow heads up while notitifcation shade disabled",
-                mStatusBar.canHeadsUp(entry, entry.sbn()));
+                mStatusBar.canHeadsUp(entry, entry.getSbn()));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index f76dc61..52b3720 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -91,6 +91,7 @@
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.NavigationBarController;
 import com.android.systemui.statusbar.NotificationEntryBuilder;
@@ -107,7 +108,7 @@
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotifPipelineInitializer;
+import com.android.systemui.statusbar.notification.NewNotifPipeline;
 import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -156,6 +157,7 @@
     private TestableNotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
     private CommandQueue mCommandQueue;
 
+    @Mock private FeatureFlags mFeatureFlags;
     @Mock private LightBarController mLightBarController;
     @Mock private StatusBarIconController mStatusBarIconController;
     @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@@ -205,7 +207,7 @@
     @Mock private KeyguardBypassController mKeyguardBypassController;
     @Mock private InjectionInflationController mInjectionInflationController;
     @Mock private DynamicPrivacyController mDynamicPrivacyController;
-    @Mock private NotifPipelineInitializer mNotifPipelineInitializer;
+    @Mock private NewNotifPipeline mNewNotifPipeline;
     @Mock private ZenModeController mZenModeController;
     @Mock private AutoHideController mAutoHideController;
     @Mock private NotificationViewHierarchyManager mNotificationViewHierarchyManager;
@@ -220,6 +222,7 @@
     @Mock private StatusBarWindowViewController.Builder mStatusBarWindowViewControllerBuilder;
     @Mock private StatusBarWindowViewController mStatusBarWindowViewController;
     @Mock private NotifLog mNotifLog;
+    @Mock private DozeParameters mDozeParameters;
 
     @Before
     public void setup() throws Exception {
@@ -287,6 +290,7 @@
 
         mStatusBar = new StatusBar(
                 mContext,
+                mFeatureFlags,
                 mLightBarController,
                 mAutoHideController,
                 mKeyguardUpdateMonitor,
@@ -301,7 +305,7 @@
                 mDynamicPrivacyController,
                 mBypassHeadsUpNotifier,
                 true,
-                mNotifPipelineInitializer,
+                () -> mNewNotifPipeline,
                 new FalsingManagerFake(),
                 mBroadcastDispatcher,
                 new RemoteInputQuickSettingsDisabler(
@@ -343,7 +347,8 @@
                 configurationController,
                 mStatusBarWindowController,
                 mStatusBarWindowViewControllerBuilder,
-                mNotifLog);
+                mNotifLog,
+                mDozeParameters);
         // TODO: we should be able to call mStatusBar.start() and have all the below values
         // initialized automatically.
         mStatusBar.mComponents = mContext.getComponents();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
index 4ffaeae..a21a658 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
@@ -32,7 +32,9 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.colorextraction.ColorExtractor;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 
@@ -48,20 +50,15 @@
 @SmallTest
 public class StatusBarWindowControllerTest extends SysuiTestCase {
 
-    @Mock
-    private WindowManager mWindowManager;
-    @Mock
-    private DozeParameters mDozeParameters;
-    @Mock
-    private ViewGroup mStatusBarView;
-    @Mock
-    private IActivityManager mActivityManager;
-    @Mock
-    private SysuiStatusBarStateController mStatusBarStateController;
-    @Mock
-    private ConfigurationController mConfigurationController;
-    @Mock
-    private KeyguardBypassController mKeyguardBypassController;
+    @Mock private WindowManager mWindowManager;
+    @Mock private DozeParameters mDozeParameters;
+    @Mock private ViewGroup mStatusBarView;
+    @Mock private IActivityManager mActivityManager;
+    @Mock private SysuiStatusBarStateController mStatusBarStateController;
+    @Mock private ConfigurationController mConfigurationController;
+    @Mock private KeyguardBypassController mKeyguardBypassController;
+    @Mock private SysuiColorExtractor mColorExtractor;
+    @Mock ColorExtractor.GradientColors mGradientColors;
 
     private StatusBarWindowController mStatusBarWindowController;
 
@@ -69,10 +66,11 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         when(mDozeParameters.getAlwaysOn()).thenReturn(true);
+        when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
 
         mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
                 mActivityManager, mDozeParameters, mStatusBarStateController,
-                mConfigurationController, mKeyguardBypassController);
+                mConfigurationController, mKeyguardBypassController, mColorExtractor);
         mStatusBarWindowController.add(mStatusBarView, 100 /* height */);
     }
 
@@ -96,9 +94,6 @@
 
     @Test
     public void testOnThemeChanged_doesntCrash() {
-        mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
-                mActivityManager, mDozeParameters, mStatusBarStateController,
-                mConfigurationController, mKeyguardBypassController);
         mStatusBarWindowController.onThemeChanged();
     }
 
@@ -109,9 +104,6 @@
 
     @Test
     public void testSetForcePluginOpen_beforeStatusBarInitialization() {
-        mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
-                mActivityManager, mDozeParameters, mStatusBarStateController,
-                mConfigurationController, mKeyguardBypassController);
         mStatusBarWindowController.setForcePluginOpen(true);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
index 0ef1acc..7c1dfa6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
@@ -70,6 +70,7 @@
     @Mock private NotificationEntryManager mNotificationEntryManager;
     @Mock private StatusBar mStatusBar;
     @Mock private DozeLog mDozeLog;
+    @Mock private DozeParameters mDozeParameters;
 
     @Before
     public void setUp() {
@@ -94,7 +95,8 @@
                 mNotificationEntryManager,
                 mKeyguardStateController,
                 mStatusBarStateController,
-                mDozeLog)
+                mDozeLog,
+                mDozeParameters)
                 .setShadeController(mShadeController)
                 .setStatusBarWindowView(mView)
                 .build();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
index 6b83fed..fc7d0ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
@@ -73,7 +73,7 @@
                 .getRecommendedTimeoutMillis(anyInt(), anyInt());
         mHeadsUpManager.showNotification(mEntry);
         Runnable pastNormalTimeRunnable =
-                () -> mLivesPastNormalTime = mHeadsUpManager.isAlerting(mEntry.key);
+                () -> mLivesPastNormalTime = mHeadsUpManager.isAlerting(mEntry.getKey());
         mTestHandler.postDelayed(pastNormalTimeRunnable,
                         (TEST_A11Y_AUTO_DISMISS_TIME + TEST_AUTO_DISMISS_TIME) / 2);
         mTestHandler.postDelayed(TEST_TIMEOUT_RUNNABLE, TEST_A11Y_TIMEOUT_TIME);
@@ -82,7 +82,7 @@
 
         assertFalse("Test timed out", mTimedOut);
         assertTrue("Heads up should live long enough", mLivesPastNormalTime);
-        assertFalse(mHeadsUpManager.isAlerting(mEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(mEntry.getKey()));
     }
 }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java
index d7df96d..54cb0b8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java
@@ -16,14 +16,14 @@
 
 package com.android.systemui.util.sensors;
 
-import android.content.Context;
+import android.content.res.Resources;
 
 public class FakeProximitySensor extends ProximitySensor {
     private boolean mAvailable;
     private boolean mPaused;
 
-    public FakeProximitySensor(Context context, AsyncSensorManager sensorManager) {
-        super(context, sensorManager);
+    public FakeProximitySensor(Resources resources, AsyncSensorManager sensorManager) {
+        super(resources, sensorManager);
 
         mAvailable = true;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java
index 1deb495..0bc7868a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java
@@ -92,6 +92,18 @@
         if (s != null) {
             return s;
         }
+        switch(type) {
+            case Sensor.TYPE_PROXIMITY:
+                try {
+                    return createSensor(Sensor.TYPE_PROXIMITY, null);
+                } catch (Exception e) {
+                    // fall through
+                }
+                break;
+            default:
+                break;
+
+        }
         // Our mock sensors aren't wakeup, and it's a pain to create them that way. Instead, just
         // return non-wakeup sensors if we can't find a wakeup sensor.
         return getDefaultSensor(type, false /* wakeup */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java
index fa943e3..37b315f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java
@@ -47,7 +47,7 @@
         AsyncSensorManager asyncSensorManager = new AsyncSensorManager(
                 sensorManager, null, new Handler());
         mFakeProximitySensor = sensorManager.getFakeProximitySensor();
-        mProximitySensor = new ProximitySensor(getContext(), asyncSensorManager);
+        mProximitySensor = new ProximitySensor(getContext().getResources(), asyncSensorManager);
     }
 
     @Test
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 5b826b1..b0e401b 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -2584,15 +2584,15 @@
 
     // ACTION: Logged when trampoline activity finishes.
     // TIME: Indicates total time taken by trampoline activity to finish in MS.
-    PROVISIONING_TRAMPOLINE_ACTIVITY_TIME_MS = 523;
+    PROVISIONING_TRAMPOLINE_ACTIVITY_TIME_MS = 523 [deprecated=true];
 
     // ACTION: Logged when encryption activity finishes.
     // TIME: Indicates total time taken by post encryption activity to finish in MS.
-    PROVISIONING_POST_ENCRYPTION_ACTIVITY_TIME_MS = 524;
+    PROVISIONING_POST_ENCRYPTION_ACTIVITY_TIME_MS = 524 [deprecated=true];
 
     // ACTION: Logged when finalization activity finishes.
     // TIME: Indicates time taken by finalization activity to finish in MS.
-    PROVISIONING_FINALIZATION_ACTIVITY_TIME_MS = 525;
+    PROVISIONING_FINALIZATION_ACTIVITY_TIME_MS = 525 [deprecated=true];
 
     // OPEN: Settings Support > Phone/Chat -> Disclaimer
     DIALOG_SUPPORT_DISCLAIMER = 526;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 91269c7..68e11df32 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -16,13 +16,6 @@
 
 package com.android.server.accessibility;
 
-import static android.accessibilityservice.AccessibilityService.SHOW_MODE_AUTO;
-import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE;
-import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN;
-import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN;
-import static android.accessibilityservice.AccessibilityService.SHOW_MODE_IGNORE_HARD_KEYBOARD;
-import static android.accessibilityservice.AccessibilityService.SHOW_MODE_MASK;
-
 import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 
@@ -50,8 +43,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.database.ContentObserver;
-import android.graphics.Point;
-import android.graphics.Rect;
 import android.graphics.Region;
 import android.hardware.display.DisplayManager;
 import android.hardware.fingerprint.IFingerprintService;
@@ -119,7 +110,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -136,6 +126,7 @@
  */
 public class AccessibilityManagerService extends IAccessibilityManager.Stub
         implements AbstractAccessibilityServiceConnection.SystemSupport,
+        AccessibilityUserState.ServiceInfoChangeListener,
         AccessibilityWindowManager.AccessibilityEventSender,
         AccessibilitySecurityPolicy.AccessibilityUserManager {
 
@@ -178,12 +169,6 @@
     private final SimpleStringSplitter mStringColonSplitter =
             new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
 
-    private final Rect mTempRect = new Rect();
-
-    private final Rect mTempRect1 = new Rect();
-
-    private final Point mTempPoint = new Point();
-
     private final PackageManager mPackageManager;
 
     private final PowerManager mPowerManager;
@@ -226,7 +211,7 @@
     private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients =
             new RemoteCallbackList<>();
 
-    private final SparseArray<UserState> mUserStates = new SparseArray<>();
+    private final SparseArray<AccessibilityUserState> mUserStates = new SparseArray<>();
 
     private final UiAutomationManager mUiAutomationManager = new UiAutomationManager(mLock);
 
@@ -237,7 +222,7 @@
 
     private boolean mIsAccessibilityButtonShown;
 
-    private UserState getCurrentUserStateLocked() {
+    private AccessibilityUserState getCurrentUserStateLocked() {
         return getUserStateLocked(mCurrentUserId);
     }
 
@@ -293,6 +278,11 @@
         return mIsAccessibilityButtonShown;
     }
 
+    @Override
+    public void onServiceInfoChangedLocked(AccessibilityUserState userState) {
+        scheduleNotifyClientsOfServicesStateChangeLocked(userState);
+    }
+
     @Nullable
     public FingerprintGestureDispatcher getFingerprintGestureDispatcher() {
         return mFingerprintGestureDispatcher;
@@ -307,40 +297,40 @@
         }
     }
 
-    private UserState getUserState(int userId) {
+    private AccessibilityUserState getUserState(int userId) {
         synchronized (mLock) {
             return getUserStateLocked(userId);
         }
     }
 
-    private UserState getUserStateLocked(int userId) {
-        UserState state = mUserStates.get(userId);
+    @NonNull
+    private AccessibilityUserState getUserStateLocked(int userId) {
+        AccessibilityUserState state = mUserStates.get(userId);
         if (state == null) {
-            state = new UserState(userId);
+            state = new AccessibilityUserState(userId, mContext, this);
             mUserStates.put(userId, state);
         }
         return state;
     }
 
     boolean getBindInstantServiceAllowed(int userId) {
-        final UserState userState = getUserState(userId);
-        if (userState == null) return false;
-        return userState.getBindInstantServiceAllowed();
+        synchronized (mLock) {
+            final AccessibilityUserState userState = getUserStateLocked(userId);
+            return userState.getBindInstantServiceAllowedLocked();
+        }
     }
 
     void setBindInstantServiceAllowed(int userId, boolean allowed) {
-        UserState userState;
+        mContext.enforceCallingOrSelfPermission(
+                Manifest.permission.MANAGE_BIND_INSTANT_SERVICE,
+                "setBindInstantServiceAllowed");
         synchronized (mLock) {
-            userState = getUserState(userId);
-            if (userState == null) {
-                if (!allowed) {
-                    return;
-                }
-                userState = new UserState(userId);
-                mUserStates.put(userId, userState);
+            final AccessibilityUserState userState = getUserStateLocked(userId);
+            if (allowed != userState.getBindInstantServiceAllowedLocked()) {
+                userState.setBindInstantServiceAllowedLocked(allowed);
+                onUserStateChangedLocked(userState);
             }
         }
-        userState.setBindInstantServiceAllowed(allowed);
     }
 
     private void registerBroadcastReceivers() {
@@ -354,7 +344,7 @@
                         return;
                     }
                     // We will update when the automation service dies.
-                    UserState userState = getCurrentUserStateLocked();
+                    AccessibilityUserState userState = getCurrentUserStateLocked();
                     // We have to reload the installed services since some services may
                     // have different attributes, resolve info (does not support equals),
                     // etc. Remove them then to force reload.
@@ -376,9 +366,11 @@
                     if (userId != mCurrentUserId) {
                         return;
                     }
-                    UserState userState = getUserStateLocked(userId);
-                    boolean reboundAService = userState.mBindingServices.removeIf(
+                    final AccessibilityUserState userState = getUserStateLocked(userId);
+                    final boolean reboundAService = userState.getBindingServicesLocked().removeIf(
                             component -> component != null
+                                    && component.getPackageName().equals(packageName))
+                            || userState.mCrashedServices.removeIf(component -> component != null
                                     && component.getPackageName().equals(packageName));
                     if (reboundAService) {
                         onUserStateChangedLocked(userState);
@@ -395,14 +387,15 @@
                     if (userId != mCurrentUserId) {
                         return;
                     }
-                    UserState userState = getUserStateLocked(userId);
+                    AccessibilityUserState userState = getUserStateLocked(userId);
                     Iterator<ComponentName> it = userState.mEnabledServices.iterator();
                     while (it.hasNext()) {
                         ComponentName comp = it.next();
                         String compPkg = comp.getPackageName();
                         if (compPkg.equals(packageName)) {
                             it.remove();
-                            userState.mBindingServices.remove(comp);
+                            userState.getBindingServicesLocked().remove(comp);
+                            userState.getCrashedServicesLocked().remove(comp);
                             // Update the enabled services setting.
                             persistComponentNamesToSettingLocked(
                                     Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
@@ -430,7 +423,7 @@
                     if (userId != mCurrentUserId) {
                         return false;
                     }
-                    UserState userState = getUserStateLocked(userId);
+                    AccessibilityUserState userState = getUserStateLocked(userId);
                     Iterator<ComponentName> it = userState.mEnabledServices.iterator();
                     while (it.hasNext()) {
                         ComponentName comp = it.next();
@@ -441,7 +434,7 @@
                                     return true;
                                 }
                                 it.remove();
-                                userState.mBindingServices.remove(comp);
+                                userState.getBindingServicesLocked().remove(comp);
                                 persistComponentNamesToSettingLocked(
                                         Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
                                         userState.mEnabledServices, userId);
@@ -478,7 +471,7 @@
                 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
                     // We will update when the automation service dies.
                     synchronized (mLock) {
-                        UserState userState = getCurrentUserStateLocked();
+                        AccessibilityUserState userState = getCurrentUserStateLocked();
                         if (readConfigurationForUserStateLocked(userState)) {
                             onUserStateChangedLocked(userState);
                         }
@@ -509,7 +502,7 @@
             // If the client is from a process that runs across users such as
             // the system UI or the system we add it to the global state that
             // is shared across users.
-            UserState userState = getUserStateLocked(resolvedUserId);
+            AccessibilityUserState userState = getUserStateLocked(resolvedUserId);
             Client client = new Client(callback, Binder.getCallingUid(), userState);
             if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
                 mGlobalClients.register(callback, client);
@@ -517,7 +510,7 @@
                     Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid());
                 }
                 return IntPair.of(
-                        userState.getClientState(),
+                        getClientStateLocked(userState),
                         client.mLastSentRelevantEventTypes);
             } else {
                 userState.mUserClients.register(callback, client);
@@ -529,7 +522,7 @@
                             + " and userId:" + mCurrentUserId);
                 }
                 return IntPair.of(
-                        (resolvedUserId == mCurrentUserId) ? userState.getClientState() : 0,
+                        (resolvedUserId == mCurrentUserId) ? getClientStateLocked(userState) : 0,
                         client.mLastSentRelevantEventTypes);
             }
         }
@@ -644,7 +637,7 @@
                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
 
             // The automation service can suppress other services.
-            final UserState userState = getUserStateLocked(resolvedUserId);
+            final AccessibilityUserState userState = getUserStateLocked(resolvedUserId);
             if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) {
                 return Collections.emptyList();
             }
@@ -754,15 +747,16 @@
         }
         synchronized (mLock) {
             // Set the temporary state.
-            UserState userState = getCurrentUserStateLocked();
+            AccessibilityUserState userState = getCurrentUserStateLocked();
 
-            userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
-            userState.mIsDisplayMagnificationEnabled = false;
-            userState.mIsNavBarMagnificationEnabled = false;
-            userState.mIsAutoclickEnabled = false;
+            userState.setTouchExplorationEnabledLocked(touchExplorationEnabled);
+            userState.setDisplayMagnificationEnabledLocked(false);
+            userState.setNavBarMagnificationEnabledLocked(false);
+            userState.setAutoclickEnabledLocked(false);
             userState.mEnabledServices.clear();
             userState.mEnabledServices.add(service);
-            userState.mBindingServices.clear();
+            userState.getBindingServicesLocked().clear();
+            userState.getCrashedServicesLocked().clear();
             userState.mTouchExplorationGrantedServices.clear();
             userState.mTouchExplorationGrantedServices.add(service);
 
@@ -943,7 +937,7 @@
             }
 
             // Disconnect from services for the old user.
-            UserState oldUserState = getCurrentUserStateLocked();
+            AccessibilityUserState oldUserState = getCurrentUserStateLocked();
             oldUserState.onSwitchToAnotherUserLocked();
 
             // Disable the local managers for the old user.
@@ -960,7 +954,7 @@
             // The user changed.
             mCurrentUserId = userId;
 
-            UserState userState = getCurrentUserStateLocked();
+            AccessibilityUserState userState = getCurrentUserStateLocked();
 
             readConfigurationForUserStateLocked(userState);
             // Even if reading did not yield change, we have to update
@@ -979,8 +973,8 @@
 
     private void announceNewUserIfNeeded() {
         synchronized (mLock) {
-            UserState userState = getCurrentUserStateLocked();
-            if (userState.isHandlingAccessibilityEvents()) {
+            AccessibilityUserState userState = getCurrentUserStateLocked();
+            if (userState.isHandlingAccessibilityEventsLocked()) {
                 UserManager userManager = (UserManager) mContext.getSystemService(
                         Context.USER_SERVICE);
                 String message = mContext.getString(R.string.user_switched,
@@ -997,7 +991,7 @@
         synchronized (mLock) {
             int parentUserId = mSecurityPolicy.resolveProfileParentLocked(userId);
             if (parentUserId == mCurrentUserId) {
-                UserState userState = getUserStateLocked(mCurrentUserId);
+                AccessibilityUserState userState = getUserStateLocked(mCurrentUserId);
                 onUserStateChangedLocked(userState);
             }
         }
@@ -1015,7 +1009,7 @@
         readComponentNamesFromStringLocked(oldSetting, mTempComponentNameSet, false);
         readComponentNamesFromStringLocked(newSetting, mTempComponentNameSet, true);
 
-        UserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
+        AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
         userState.mEnabledServices.clear();
         userState.mEnabledServices.addAll(mTempComponentNameSet);
         persistComponentNamesToSettingLocked(
@@ -1025,6 +1019,10 @@
         onUserStateChangedLocked(userState);
     }
 
+    private int getClientStateLocked(AccessibilityUserState userState) {
+        return userState.getClientStateLocked(mUiAutomationManager.isUiAutomationRunningLocked());
+    }
+
     private InteractionBridge getInteractionBridge() {
         synchronized (mLock) {
             if (mInteractionBridge == null) {
@@ -1044,7 +1042,7 @@
         //       gestures to avoid user frustration when different
         //       behavior is observed from different combinations of
         //       enabled accessibility services.
-        UserState state = getCurrentUserStateLocked();
+        AccessibilityUserState state = getCurrentUserStateLocked();
         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
             AccessibilityServiceConnection service = state.mBoundServices.get(i);
             if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) {
@@ -1056,7 +1054,7 @@
     }
 
     private void notifyClearAccessibilityCacheLocked() {
-        UserState state = getCurrentUserStateLocked();
+        AccessibilityUserState state = getCurrentUserStateLocked();
         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
             AccessibilityServiceConnection service = state.mBoundServices.get(i);
             service.notifyClearAccessibilityNodeInfoCache();
@@ -1065,25 +1063,17 @@
 
     private void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
             float scale, float centerX, float centerY) {
-        final UserState state = getCurrentUserStateLocked();
+        final AccessibilityUserState state = getCurrentUserStateLocked();
         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
             final AccessibilityServiceConnection service = state.mBoundServices.get(i);
             service.notifyMagnificationChangedLocked(displayId, region, scale, centerX, centerY);
         }
     }
 
-    private void notifySoftKeyboardShowModeChangedLocked(int showMode) {
-        final UserState state = getCurrentUserStateLocked();
-        for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
-            final AccessibilityServiceConnection service = state.mBoundServices.get(i);
-            service.notifySoftKeyboardShowModeChangedLocked(showMode);
-        }
-    }
-
     private void notifyAccessibilityButtonClickedLocked(int displayId) {
-        final UserState state = getCurrentUserStateLocked();
+        final AccessibilityUserState state = getCurrentUserStateLocked();
 
-        int potentialTargets = state.mIsNavBarMagnificationEnabled ? 1 : 0;
+        int potentialTargets = state.isNavBarMagnificationEnabledLocked() ? 1 : 0;
         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
             final AccessibilityServiceConnection service = state.mBoundServices.get(i);
             if (service.mRequestAccessibilityButton) {
@@ -1095,7 +1085,7 @@
             return;
         }
         if (potentialTargets == 1) {
-            if (state.mIsNavBarMagnificationEnabled) {
+            if (state.isNavBarMagnificationEnabledLocked()) {
                 mMainHandler.sendMessage(obtainMessage(
                         AccessibilityManagerService::sendAccessibilityButtonToInputFilter, this,
                         displayId));
@@ -1110,13 +1100,13 @@
                 }
             }
         } else {
-            if (state.mServiceAssignedToAccessibilityButton == null
-                    && !state.mIsNavBarMagnificationAssignedToAccessibilityButton) {
+            if (state.getServiceAssignedToAccessibilityButtonLocked() == null
+                    && !state.isNavBarMagnificationAssignedToAccessibilityButtonLocked()) {
                 mMainHandler.sendMessage(obtainMessage(
                         AccessibilityManagerService::showAccessibilityButtonTargetSelection, this,
                         displayId));
-            } else if (state.mIsNavBarMagnificationEnabled
-                    && state.mIsNavBarMagnificationAssignedToAccessibilityButton) {
+            } else if (state.isNavBarMagnificationEnabledLocked()
+                    && state.isNavBarMagnificationAssignedToAccessibilityButtonLocked()) {
                 mMainHandler.sendMessage(obtainMessage(
                         AccessibilityManagerService::sendAccessibilityButtonToInputFilter, this,
                         displayId));
@@ -1125,7 +1115,7 @@
                 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
                     final AccessibilityServiceConnection service = state.mBoundServices.get(i);
                     if (service.mRequestAccessibilityButton && (service.mComponentName.equals(
-                            state.mServiceAssignedToAccessibilityButton))) {
+                            state.getServiceAssignedToAccessibilityButtonLocked()))) {
                         service.notifyAccessibilityButtonClickedLocked(displayId);
                         return;
                     }
@@ -1154,7 +1144,7 @@
     }
 
     private void notifyAccessibilityButtonVisibilityChangedLocked(boolean available) {
-        final UserState state = getCurrentUserStateLocked();
+        final AccessibilityUserState state = getCurrentUserStateLocked();
         mIsAccessibilityButtonShown = available;
         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
             final AccessibilityServiceConnection clientConnection = state.mBoundServices.get(i);
@@ -1165,7 +1155,7 @@
         }
     }
 
-    private boolean readInstalledAccessibilityServiceLocked(UserState userState) {
+    private boolean readInstalledAccessibilityServiceLocked(AccessibilityUserState userState) {
         mTempAccessibilityServiceInfoList.clear();
 
         int flags = PackageManager.GET_SERVICES
@@ -1174,7 +1164,7 @@
                 | PackageManager.MATCH_DIRECT_BOOT_AWARE
                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 
-        if (userState.getBindInstantServiceAllowed()) {
+        if (userState.getBindInstantServiceAllowedLocked()) {
             flags |= PackageManager.MATCH_INSTANT;
         }
 
@@ -1192,6 +1182,10 @@
             AccessibilityServiceInfo accessibilityServiceInfo;
             try {
                 accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
+                if (userState.mCrashedServices.contains(serviceInfo.getComponentName())) {
+                    // Restore the crashed attribute.
+                    accessibilityServiceInfo.crashed = true;
+                }
                 mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo);
             } catch (XmlPullParserException | IOException xppe) {
                 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe);
@@ -1209,7 +1203,7 @@
         return false;
     }
 
-    private boolean readInstalledAccessibilityShortcutLocked(UserState userState) {
+    private boolean readInstalledAccessibilityShortcutLocked(AccessibilityUserState userState) {
         final List<AccessibilityShortcutInfo> shortcutInfos = AccessibilityManager
                 .getInstance(mContext).getInstalledAccessibilityShortcutListAsUser(
                         mContext, mCurrentUserId);
@@ -1221,7 +1215,7 @@
         return false;
     }
 
-    private boolean readEnabledAccessibilityServicesLocked(UserState userState) {
+    private boolean readEnabledAccessibilityServicesLocked(AccessibilityUserState userState) {
         mTempComponentNameSet.clear();
         readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
                 userState.mUserId, mTempComponentNameSet);
@@ -1236,7 +1230,7 @@
     }
 
     private boolean readTouchExplorationGrantedAccessibilityServicesLocked(
-            UserState userState) {
+            AccessibilityUserState userState) {
         mTempComponentNameSet.clear();
         readComponentNamesFromSettingLocked(
                 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
@@ -1261,7 +1255,7 @@
     private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event,
             boolean isDefault) {
         try {
-            UserState state = getCurrentUserStateLocked();
+            AccessibilityUserState state = getCurrentUserStateLocked();
             for (int i = 0, count = state.mBoundServices.size(); i < count; i++) {
                 AccessibilityServiceConnection service = state.mBoundServices.get(i);
 
@@ -1276,7 +1270,7 @@
         }
     }
 
-    private void updateRelevantEventsLocked(UserState userState) {
+    private void updateRelevantEventsLocked(AccessibilityUserState userState) {
         mMainHandler.post(() -> {
             broadcastToClients(userState, ignoreRemoteException(client -> {
                 int relevantEventTypes;
@@ -1296,7 +1290,7 @@
         });
     }
 
-    private int computeRelevantEventTypesLocked(UserState userState, Client client) {
+    private int computeRelevantEventTypesLocked(AccessibilityUserState userState, Client client) {
         int relevantEventTypes = 0;
 
         int serviceCount = userState.mBoundServices.size();
@@ -1342,20 +1336,11 @@
     }
 
     private void broadcastToClients(
-            UserState userState, Consumer<Client> clientAction) {
+            AccessibilityUserState userState, Consumer<Client> clientAction) {
         mGlobalClients.broadcastForEachCookie(clientAction);
         userState.mUserClients.broadcastForEachCookie(clientAction);
     }
 
-    private void unbindAllServicesLocked(UserState userState) {
-        List<AccessibilityServiceConnection> services = userState.mBoundServices;
-        for (int count = services.size(); count > 0; count--) {
-            // When the service is unbound, it disappears from the list, so there's no need to
-            // keep track of the index
-            services.get(0).unbindLocked();
-        }
-    }
-
     /**
      * Populates a set with the {@link ComponentName}s stored in a colon
      * separated value setting for a given user.
@@ -1422,7 +1407,7 @@
         }
     }
 
-    private void updateServicesLocked(UserState userState) {
+    private void updateServicesLocked(AccessibilityUserState userState) {
         Map<ComponentName, AccessibilityServiceConnection> componentNameToServiceMap =
                 userState.mComponentNameToServiceMap;
         boolean isUnlockingOrUnlocked = LocalServices.getService(UserManagerInternal.class)
@@ -1441,8 +1426,9 @@
                 continue;
             }
 
-            // Wait for the binding if it is in process.
-            if (userState.mBindingServices.contains(componentName)) {
+            // Skip the component since it may be in process or crashed.
+            if (userState.getBindingServicesLocked().contains(componentName)
+                    || userState.getCrashedServicesLocked().contains(componentName)) {
                 continue;
             }
             if (userState.mEnabledServices.contains(componentName)
@@ -1478,15 +1464,15 @@
         if (audioManager != null) {
             audioManager.setAccessibilityServiceUids(mTempIntArray);
         }
-        updateAccessibilityEnabledSetting(userState);
+        updateAccessibilityEnabledSettingLocked(userState);
     }
 
-    private void scheduleUpdateClientsIfNeededLocked(UserState userState) {
-        final int clientState = userState.getClientState();
-        if (userState.mLastSentClientState != clientState
+    private void scheduleUpdateClientsIfNeededLocked(AccessibilityUserState userState) {
+        final int clientState = getClientStateLocked(userState);
+        if (userState.getLastSentClientStateLocked() != clientState
                 && (mGlobalClients.getRegisteredCallbackCount() > 0
                         || userState.mUserClients.getRegisteredCallbackCount() > 0)) {
-            userState.mLastSentClientState = clientState;
+            userState.setLastSentClientStateLocked(clientState);
             mMainHandler.sendMessage(obtainMessage(
                     AccessibilityManagerService::sendStateToAllClients,
                     this, clientState, userState.mUserId));
@@ -1508,7 +1494,8 @@
                 client -> client.setState(clientState)));
     }
 
-    private void scheduleNotifyClientsOfServicesStateChangeLocked(UserState userState) {
+    private void scheduleNotifyClientsOfServicesStateChangeLocked(
+            AccessibilityUserState userState) {
         updateRecommendedUiTimeoutLocked(userState);
         mMainHandler.sendMessage(obtainMessage(
                 AccessibilityManagerService::sendServicesStateChanged,
@@ -1527,44 +1514,45 @@
                 client -> client.notifyServicesStateChanged(uiTimeout)));
     }
 
-    private void scheduleUpdateInputFilter(UserState userState) {
+    private void scheduleUpdateInputFilter(AccessibilityUserState userState) {
         mMainHandler.sendMessage(obtainMessage(
                 AccessibilityManagerService::updateInputFilter, this, userState));
     }
 
-    private void scheduleUpdateFingerprintGestureHandling(UserState userState) {
+    private void scheduleUpdateFingerprintGestureHandling(AccessibilityUserState userState) {
         mMainHandler.sendMessage(obtainMessage(
                 AccessibilityManagerService::updateFingerprintGestureHandling,
                 this, userState));
     }
 
-    private void updateInputFilter(UserState userState) {
+    private void updateInputFilter(AccessibilityUserState userState) {
         if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) return;
 
         boolean setInputFilter = false;
         AccessibilityInputFilter inputFilter = null;
         synchronized (mLock) {
             int flags = 0;
-            if (userState.mIsDisplayMagnificationEnabled) {
+            if (userState.isDisplayMagnificationEnabledLocked()) {
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
             }
-            if (userState.mIsNavBarMagnificationEnabled) {
+            if (userState.isNavBarMagnificationEnabledLocked()) {
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER;
             }
             if (userHasMagnificationServicesLocked(userState)) {
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER;
             }
             // Touch exploration without accessibility makes no sense.
-            if (userState.isHandlingAccessibilityEvents() && userState.mIsTouchExplorationEnabled) {
+            if (userState.isHandlingAccessibilityEventsLocked()
+                    && userState.isTouchExplorationEnabledLocked()) {
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
             }
-            if (userState.mIsFilterKeyEventsEnabled) {
+            if (userState.isFilterKeyEventsEnabledLocked()) {
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS;
             }
-            if (userState.mIsAutoclickEnabled) {
+            if (userState.isAutoclickEnabledLocked()) {
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_AUTOCLICK;
             }
-            if (userState.mIsPerformGesturesEnabled) {
+            if (userState.isPerformGesturesEnabledLocked()) {
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_INJECT_MOTION_EVENTS;
             }
             if (flags != 0) {
@@ -1597,8 +1585,8 @@
             String label = service.getServiceInfo().getResolveInfo()
                     .loadLabel(mContext.getPackageManager()).toString();
 
-            final UserState userState = getCurrentUserStateLocked();
-            if (userState.mIsTouchExplorationEnabled) {
+            final AccessibilityUserState userState = getCurrentUserStateLocked();
+            if (userState.isTouchExplorationEnabledLocked()) {
                 return;
             }
             if (mEnableTouchExplorationDialog != null
@@ -1608,40 +1596,40 @@
             mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
                 .setIconAttribute(android.R.attr.alertDialogIcon)
                 .setPositiveButton(android.R.string.ok, new OnClickListener() {
-                     @Override
-                     public void onClick(DialogInterface dialog, int which) {
-                         // The user allowed the service to toggle touch exploration.
-                         userState.mTouchExplorationGrantedServices.add(service.mComponentName);
-                         persistComponentNamesToSettingLocked(
-                                 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
-                                 userState.mTouchExplorationGrantedServices, userState.mUserId);
-                         // Enable touch exploration.
-                         userState.mIsTouchExplorationEnabled = true;
-                         final long identity = Binder.clearCallingIdentity();
-                         try {
-                             Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                                     Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1,
-                                     userState.mUserId);
-                         } finally {
-                             Binder.restoreCallingIdentity(identity);
-                         }
-                         onUserStateChangedLocked(userState);
-                     }
-                 })
-                 .setNegativeButton(android.R.string.cancel, new OnClickListener() {
-                     @Override
-                     public void onClick(DialogInterface dialog, int which) {
-                         dialog.dismiss();
-                     }
-                 })
-                 .setTitle(R.string.enable_explore_by_touch_warning_title)
-                 .setMessage(mContext.getString(
-                         R.string.enable_explore_by_touch_warning_message, label))
-                 .create();
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        // The user allowed the service to toggle touch exploration.
+                        userState.mTouchExplorationGrantedServices.add(service.mComponentName);
+                        persistComponentNamesToSettingLocked(
+                                Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+                                userState.mTouchExplorationGrantedServices, userState.mUserId);
+                        // Enable touch exploration.
+                        userState.setTouchExplorationEnabledLocked(true);
+                        final long identity = Binder.clearCallingIdentity();
+                        try {
+                            Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                                    Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1,
+                                    userState.mUserId);
+                        } finally {
+                            Binder.restoreCallingIdentity(identity);
+                        }
+                        onUserStateChangedLocked(userState);
+                    }
+                })
+                .setNegativeButton(android.R.string.cancel, new OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        dialog.dismiss();
+                    }
+                })
+                .setTitle(R.string.enable_explore_by_touch_warning_title)
+                .setMessage(mContext.getString(
+                        R.string.enable_explore_by_touch_warning_message, label))
+                .create();
              mEnableTouchExplorationDialog.getWindow().setType(
                      WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
              mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags
-                     |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+                     |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
              mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
              mEnableTouchExplorationDialog.show();
         }
@@ -1652,7 +1640,7 @@
      *
      * @param userState the new user state
      */
-    private void onUserStateChangedLocked(UserState userState) {
+    private void onUserStateChangedLocked(AccessibilityUserState userState) {
         // TODO: Remove this hack
         mInitialized = true;
         updateLegacyCapabilitiesLocked(userState);
@@ -1670,7 +1658,7 @@
         updateAccessibilityButtonTargetsLocked(userState);
     }
 
-    private void updateWindowsForAccessibilityCallbackLocked(UserState userState) {
+    private void updateWindowsForAccessibilityCallbackLocked(AccessibilityUserState userState) {
         // We observe windows for accessibility only if there is at least
         // one bound service that can retrieve window content that specified
         // it is interested in accessing such windows. For services that are
@@ -1702,7 +1690,7 @@
         }
     }
 
-    private void updateLegacyCapabilitiesLocked(UserState userState) {
+    private void updateLegacyCapabilitiesLocked(AccessibilityUserState userState) {
         // Up to JB-MR1 we had a white list with services that can enable touch
         // exploration. When a service is first started we show a dialog to the
         // use to get a permission to white list the service.
@@ -1724,20 +1712,20 @@
         }
     }
 
-    private void updatePerformGesturesLocked(UserState userState) {
+    private void updatePerformGesturesLocked(AccessibilityUserState userState) {
         final int serviceCount = userState.mBoundServices.size();
         for (int i = 0; i < serviceCount; i++) {
             AccessibilityServiceConnection service = userState.mBoundServices.get(i);
             if ((service.getCapabilities()
                     & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0) {
-                userState.mIsPerformGesturesEnabled = true;
+                userState.setPerformGesturesEnabledLocked(true);
                 return;
             }
         }
-        userState.mIsPerformGesturesEnabled = false;
+        userState.setPerformGesturesEnabledLocked(false);
     }
 
-    private void updateFilterKeyEventsLocked(UserState userState) {
+    private void updateFilterKeyEventsLocked(AccessibilityUserState userState) {
         final int serviceCount = userState.mBoundServices.size();
         for (int i = 0; i < serviceCount; i++) {
             AccessibilityServiceConnection service = userState.mBoundServices.get(i);
@@ -1745,14 +1733,14 @@
                     && (service.getCapabilities()
                             & AccessibilityServiceInfo
                             .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) {
-                userState.mIsFilterKeyEventsEnabled = true;
+                userState.setFilterKeyEventsEnabledLocked(true);
                 return;
             }
         }
-        userState.mIsFilterKeyEventsEnabled = false;
+        userState.setFilterKeyEventsEnabledLocked(false);
     }
 
-    private boolean readConfigurationForUserStateLocked(UserState userState) {
+    private boolean readConfigurationForUserStateLocked(AccessibilityUserState userState) {
         boolean somethingChanged = readInstalledAccessibilityServiceLocked(userState);
         somethingChanged |= readInstalledAccessibilityShortcutLocked(userState);
         somethingChanged |= readEnabledAccessibilityServicesLocked(userState);
@@ -1767,10 +1755,10 @@
         return somethingChanged;
     }
 
-    private void updateAccessibilityEnabledSetting(UserState userState) {
+    private void updateAccessibilityEnabledSettingLocked(AccessibilityUserState userState) {
         final long identity = Binder.clearCallingIdentity();
         final boolean isA11yEnabled = mUiAutomationManager.isUiAutomationRunningLocked()
-                || userState.isHandlingAccessibilityEvents();
+                || userState.isHandlingAccessibilityEventsLocked();
         try {
             Settings.Secure.putIntForUser(mContext.getContentResolver(),
                     Settings.Secure.ACCESSIBILITY_ENABLED,
@@ -1781,18 +1769,18 @@
         }
     }
 
-    private boolean readTouchExplorationEnabledSettingLocked(UserState userState) {
+    private boolean readTouchExplorationEnabledSettingLocked(AccessibilityUserState userState) {
         final boolean touchExplorationEnabled = Settings.Secure.getIntForUser(
                 mContext.getContentResolver(),
                 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1;
-        if (touchExplorationEnabled != userState.mIsTouchExplorationEnabled) {
-            userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
+        if (touchExplorationEnabled != userState.isTouchExplorationEnabledLocked()) {
+            userState.setTouchExplorationEnabledLocked(touchExplorationEnabled);
             return true;
         }
         return false;
     }
 
-    private boolean readMagnificationEnabledSettingsLocked(UserState userState) {
+    private boolean readMagnificationEnabledSettingsLocked(AccessibilityUserState userState) {
         final boolean displayMagnificationEnabled = Settings.Secure.getIntForUser(
                 mContext.getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
@@ -1801,40 +1789,40 @@
                 mContext.getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
                 0, userState.mUserId) == 1;
-        if ((displayMagnificationEnabled != userState.mIsDisplayMagnificationEnabled)
-                || (navBarMagnificationEnabled != userState.mIsNavBarMagnificationEnabled)) {
-            userState.mIsDisplayMagnificationEnabled = displayMagnificationEnabled;
-            userState.mIsNavBarMagnificationEnabled = navBarMagnificationEnabled;
+        if ((displayMagnificationEnabled != userState.isDisplayMagnificationEnabledLocked())
+                || (navBarMagnificationEnabled != userState.isNavBarMagnificationEnabledLocked())) {
+            userState.setDisplayMagnificationEnabledLocked(displayMagnificationEnabled);
+            userState.setNavBarMagnificationEnabledLocked(navBarMagnificationEnabled);
             return true;
         }
         return false;
     }
 
-    private boolean readAutoclickEnabledSettingLocked(UserState userState) {
+    private boolean readAutoclickEnabledSettingLocked(AccessibilityUserState userState) {
         final boolean autoclickEnabled = Settings.Secure.getIntForUser(
                 mContext.getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED,
                 0, userState.mUserId) == 1;
-        if (autoclickEnabled != userState.mIsAutoclickEnabled) {
-            userState.mIsAutoclickEnabled = autoclickEnabled;
+        if (autoclickEnabled != userState.isAutoclickEnabledLocked()) {
+            userState.setAutoclickEnabledLocked(autoclickEnabled);
             return true;
         }
         return false;
     }
 
-    private boolean readHighTextContrastEnabledSettingLocked(UserState userState) {
+    private boolean readHighTextContrastEnabledSettingLocked(AccessibilityUserState userState) {
         final boolean highTextContrastEnabled = Settings.Secure.getIntForUser(
                 mContext.getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0,
                 userState.mUserId) == 1;
-        if (highTextContrastEnabled != userState.mIsTextHighContrastEnabled) {
-            userState.mIsTextHighContrastEnabled = highTextContrastEnabled;
+        if (highTextContrastEnabled != userState.isTextHighContrastEnabledLocked()) {
+            userState.setTextHighContrastEnabledLocked(highTextContrastEnabled);
             return true;
         }
         return false;
     }
 
-    private void updateTouchExplorationLocked(UserState userState) {
+    private void updateTouchExplorationLocked(AccessibilityUserState userState) {
         boolean enabled = mUiAutomationManager.isTouchExplorationEnabledLocked();
         final int serviceCount = userState.mBoundServices.size();
         for (int i = 0; i < serviceCount; i++) {
@@ -1844,8 +1832,8 @@
                 break;
             }
         }
-        if (enabled != userState.mIsTouchExplorationEnabled) {
-            userState.mIsTouchExplorationEnabled = enabled;
+        if (enabled != userState.isTouchExplorationEnabledLocked()) {
+            userState.setTouchExplorationEnabledLocked(enabled);
             final long identity = Binder.clearCallingIdentity();
             try {
                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
@@ -1857,60 +1845,61 @@
         }
     }
 
-    private boolean readAccessibilityShortcutSettingLocked(UserState userState) {
+    private boolean readAccessibilityShortcutSettingLocked(AccessibilityUserState userState) {
         String componentNameToEnableString = AccessibilityShortcutController
                 .getTargetServiceComponentNameString(mContext, userState.mUserId);
         if ((componentNameToEnableString == null) || componentNameToEnableString.isEmpty()) {
-            if (userState.mServiceToEnableWithShortcut == null) {
+            if (userState.getServiceToEnableWithShortcutLocked() == null) {
                 return false;
             }
-            userState.mServiceToEnableWithShortcut = null;
+            userState.setServiceToEnableWithShortcutLocked(null);
             return true;
         }
         ComponentName componentNameToEnable =
             ComponentName.unflattenFromString(componentNameToEnableString);
         if ((componentNameToEnable != null)
-                && componentNameToEnable.equals(userState.mServiceToEnableWithShortcut)) {
+                && componentNameToEnable.equals(userState.getServiceToEnableWithShortcutLocked())) {
             return false;
         }
 
-        userState.mServiceToEnableWithShortcut = componentNameToEnable;
+        userState.setServiceToEnableWithShortcutLocked(componentNameToEnable);
         scheduleNotifyClientsOfServicesStateChangeLocked(userState);
         return true;
     }
 
-    private boolean readAccessibilityButtonSettingsLocked(UserState userState) {
+    private boolean readAccessibilityButtonSettingsLocked(AccessibilityUserState userState) {
         String componentId = Settings.Secure.getStringForUser(mContext.getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, userState.mUserId);
         if (TextUtils.isEmpty(componentId)) {
-            if ((userState.mServiceAssignedToAccessibilityButton == null)
-                    && !userState.mIsNavBarMagnificationAssignedToAccessibilityButton) {
+            if ((userState.getServiceAssignedToAccessibilityButtonLocked() == null)
+                    && !userState.isNavBarMagnificationAssignedToAccessibilityButtonLocked()) {
                 return false;
             }
-            userState.mServiceAssignedToAccessibilityButton = null;
-            userState.mIsNavBarMagnificationAssignedToAccessibilityButton = false;
+            userState.setServiceAssignedToAccessibilityButtonLocked(null);
+            userState.setNavBarMagnificationAssignedToAccessibilityButtonLocked(false);
             return true;
         }
 
         if (componentId.equals(MagnificationController.class.getName())) {
-            if (userState.mIsNavBarMagnificationAssignedToAccessibilityButton) {
+            if (userState.isNavBarMagnificationAssignedToAccessibilityButtonLocked()) {
                 return false;
             }
-            userState.mServiceAssignedToAccessibilityButton = null;
-            userState.mIsNavBarMagnificationAssignedToAccessibilityButton = true;
+            userState.setServiceAssignedToAccessibilityButtonLocked(null);
+            userState.setNavBarMagnificationAssignedToAccessibilityButtonLocked(true);
             return true;
         }
 
         ComponentName componentName = ComponentName.unflattenFromString(componentId);
-        if (Objects.equals(componentName, userState.mServiceAssignedToAccessibilityButton)) {
+        if (Objects.equals(componentName,
+                userState.getServiceAssignedToAccessibilityButtonLocked())) {
             return false;
         }
-        userState.mServiceAssignedToAccessibilityButton = componentName;
-        userState.mIsNavBarMagnificationAssignedToAccessibilityButton = false;
+        userState.setServiceAssignedToAccessibilityButtonLocked(componentName);
+        userState.setNavBarMagnificationAssignedToAccessibilityButtonLocked(false);
         return true;
     }
 
-    private boolean readUserRecommendedUiTimeoutSettingsLocked(UserState userState) {
+    private boolean readUserRecommendedUiTimeoutSettingsLocked(AccessibilityUserState userState) {
         final int nonInteractiveUiTimeout = Settings.Secure.getIntForUser(
                 mContext.getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, 0,
@@ -1919,10 +1908,10 @@
                 mContext.getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, 0,
                 userState.mUserId);
-        if (nonInteractiveUiTimeout != userState.mUserNonInteractiveUiTimeout
-                || interactiveUiTimeout != userState.mUserInteractiveUiTimeout) {
-            userState.mUserNonInteractiveUiTimeout = nonInteractiveUiTimeout;
-            userState.mUserInteractiveUiTimeout = interactiveUiTimeout;
+        if (nonInteractiveUiTimeout != userState.getUserNonInteractiveUiTimeoutLocked()
+                || interactiveUiTimeout != userState.getUserInteractiveUiTimeoutLocked()) {
+            userState.setUserNonInteractiveUiTimeoutLocked(nonInteractiveUiTimeout);
+            userState.setUserInteractiveUiTimeoutLocked(interactiveUiTimeout);
             scheduleNotifyClientsOfServicesStateChangeLocked(userState);
             return true;
         }
@@ -1936,22 +1925,22 @@
      *
      * @param userState
      */
-    private void updateAccessibilityShortcutLocked(UserState userState) {
-        if (userState.mServiceToEnableWithShortcut == null) {
+    private void updateAccessibilityShortcutLocked(AccessibilityUserState userState) {
+        if (userState.getServiceToEnableWithShortcutLocked() == null) {
             return;
         }
         boolean shortcutServiceIsInstalled =
                 AccessibilityShortcutController.getFrameworkShortcutFeaturesMap()
-                        .containsKey(userState.mServiceToEnableWithShortcut);
+                        .containsKey(userState.getServiceToEnableWithShortcutLocked());
         for (int i = 0; !shortcutServiceIsInstalled && (i < userState.mInstalledServices.size());
                 i++) {
             if (userState.mInstalledServices.get(i).getComponentName()
-                    .equals(userState.mServiceToEnableWithShortcut)) {
+                    .equals(userState.getServiceToEnableWithShortcutLocked())) {
                 shortcutServiceIsInstalled = true;
             }
         }
         if (!shortcutServiceIsInstalled) {
-            userState.mServiceToEnableWithShortcut = null;
+            userState.setServiceToEnableWithShortcutLocked(null);
             final long identity = Binder.clearCallingIdentity();
             try {
                 Settings.Secure.putStringForUser(mContext.getContentResolver(),
@@ -1967,7 +1956,7 @@
     }
 
     private boolean canRequestAndRequestsTouchExplorationLocked(
-            AccessibilityServiceConnection service, UserState userState) {
+            AccessibilityServiceConnection service, AccessibilityUserState userState) {
         // Service not ready or cannot request the feature - well nothing to do.
         if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) {
             return false;
@@ -1997,7 +1986,7 @@
         return false;
     }
 
-    private void updateMagnificationLocked(UserState userState) {
+    private void updateMagnificationLocked(AccessibilityUserState userState) {
         if (userState.mUserId != mCurrentUserId) {
             return;
         }
@@ -2012,8 +2001,8 @@
         // We would skip overlay display because it uses overlay window to simulate secondary
         // displays in one display. It's not a real display and there's no input events for it.
         final ArrayList<Display> displays = getValidDisplayList();
-        if (userState.mIsDisplayMagnificationEnabled
-                || userState.mIsNavBarMagnificationEnabled) {
+        if (userState.isDisplayMagnificationEnabledLocked()
+                || userState.isNavBarMagnificationEnabledLocked()) {
             for (int i = 0; i < displays.size(); i++) {
                 final Display display = displays.get(i);
                 getMagnificationController().register(display.getDisplayId());
@@ -2037,7 +2026,7 @@
      * Returns whether the specified user has any services that are capable of
      * controlling magnification.
      */
-    private boolean userHasMagnificationServicesLocked(UserState userState) {
+    private boolean userHasMagnificationServicesLocked(AccessibilityUserState userState) {
         final List<AccessibilityServiceConnection> services = userState.mBoundServices;
         for (int i = 0, count = services.size(); i < count; i++) {
             final AccessibilityServiceConnection service = services.get(i);
@@ -2052,7 +2041,7 @@
      * Returns whether the specified user has any services that are capable of
      * controlling magnification and are actively listening for magnification updates.
      */
-    private boolean userHasListeningMagnificationServicesLocked(UserState userState,
+    private boolean userHasListeningMagnificationServicesLocked(AccessibilityUserState userState,
             int displayId) {
         final List<AccessibilityServiceConnection> services = userState.mBoundServices;
         for (int i = 0, count = services.size(); i < count; i++) {
@@ -2065,7 +2054,7 @@
         return false;
     }
 
-    private void updateFingerprintGestureHandling(UserState userState) {
+    private void updateFingerprintGestureHandling(AccessibilityUserState userState) {
         final List<AccessibilityServiceConnection> services;
         synchronized (mLock) {
             services = userState.mBoundServices;
@@ -2097,7 +2086,7 @@
         }
     }
 
-    private void updateAccessibilityButtonTargetsLocked(UserState userState) {
+    private void updateAccessibilityButtonTargetsLocked(AccessibilityUserState userState) {
         for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
             final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
             if (service.mRequestAccessibilityButton) {
@@ -2107,9 +2096,9 @@
         }
     }
 
-    private void updateRecommendedUiTimeoutLocked(UserState userState) {
-        int newNonInteractiveUiTimeout = userState.mUserNonInteractiveUiTimeout;
-        int newInteractiveUiTimeout = userState.mUserInteractiveUiTimeout;
+    private void updateRecommendedUiTimeoutLocked(AccessibilityUserState userState) {
+        int newNonInteractiveUiTimeout = userState.getUserNonInteractiveUiTimeoutLocked();
+        int newInteractiveUiTimeout = userState.getUserInteractiveUiTimeoutLocked();
         // read from a11y services if user does not specify value
         if (newNonInteractiveUiTimeout == 0 || newInteractiveUiTimeout == 0) {
             int serviceNonInteractiveUiTimeout = 0;
@@ -2132,8 +2121,8 @@
                 newInteractiveUiTimeout = serviceInteractiveUiTimeout;
             }
         }
-        userState.mNonInteractiveUiTimeout = newNonInteractiveUiTimeout;
-        userState.mInteractiveUiTimeout = newInteractiveUiTimeout;
+        userState.setNonInteractiveUiTimeoutLocked(newNonInteractiveUiTimeout);
+        userState.setInteractiveUiTimeoutLocked(newInteractiveUiTimeout);
     }
 
     @GuardedBy("mLock")
@@ -2180,8 +2169,8 @@
         final Map<ComponentName, ToggleableFrameworkFeatureInfo> frameworkFeatureMap =
                 AccessibilityShortcutController.getFrameworkShortcutFeaturesMap();
         synchronized(mLock) {
-            final UserState userState = getUserStateLocked(mCurrentUserId);
-            final ComponentName serviceName = userState.mServiceToEnableWithShortcut;
+            final AccessibilityUserState userState = getUserStateLocked(mCurrentUserId);
+            final ComponentName serviceName = userState.getServiceToEnableWithShortcutLocked();
             if (serviceName == null) {
                 return;
             }
@@ -2218,11 +2207,11 @@
                     "getAccessibilityShortcutService requires the MANAGE_ACCESSIBILITY permission");
         }
         synchronized(mLock) {
-            final UserState userState = getUserStateLocked(mCurrentUserId);
-            if (userState.mServiceToEnableWithShortcut == null) {
+            final AccessibilityUserState userState = getUserStateLocked(mCurrentUserId);
+            if (userState.getServiceToEnableWithShortcutLocked() == null) {
                 return null;
             }
-            return userState.mServiceToEnableWithShortcut.flattenToString();
+            return userState.getServiceToEnableWithShortcutLocked().flattenToString();
         }
     }
 
@@ -2237,7 +2226,7 @@
                         userId);
         setting.write(ComponentNameSet.add(setting.read(), componentName));
 
-        UserState userState = getUserStateLocked(userId);
+        AccessibilityUserState userState = getUserStateLocked(userId);
         if (userState.mEnabledServices.add(componentName)) {
             onUserStateChangedLocked(userState);
         }
@@ -2254,7 +2243,7 @@
                         userId);
         setting.write(ComponentNameSet.remove(setting.read(), componentName));
 
-        UserState userState = getUserStateLocked(userId);
+        AccessibilityUserState userState = getUserStateLocked(userId);
         if (userState.mEnabledServices.remove(componentName)) {
             onUserStateChangedLocked(userState);
         }
@@ -2322,14 +2311,14 @@
     @Override
     public long getRecommendedTimeoutMillis() {
         synchronized(mLock) {
-            final UserState userState = getCurrentUserStateLocked();
+            final AccessibilityUserState userState = getCurrentUserStateLocked();
             return getRecommendedTimeoutMillisLocked(userState);
         }
     }
 
-    private long getRecommendedTimeoutMillisLocked(UserState userState) {
-        return IntPair.of(userState.mInteractiveUiTimeout,
-                userState.mNonInteractiveUiTimeout);
+    private long getRecommendedTimeoutMillisLocked(AccessibilityUserState userState) {
+        return IntPair.of(userState.getInteractiveUiTimeoutLocked(),
+                userState.getNonInteractiveUiTimeoutLocked());
     }
 
     @Override
@@ -2338,78 +2327,20 @@
         synchronized (mLock) {
             pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)");
             pw.println();
+            pw.append("currentUserId=").append(String.valueOf(mCurrentUserId));
+            pw.println();
             final int userCount = mUserStates.size();
             for (int i = 0; i < userCount; i++) {
-                UserState userState = mUserStates.valueAt(i);
-                pw.append("User state[attributes:{id=" + userState.mUserId);
-                pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId));
-                pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled);
-                pw.append(", displayMagnificationEnabled="
-                        + userState.mIsDisplayMagnificationEnabled);
-                pw.append(", navBarMagnificationEnabled="
-                        + userState.mIsNavBarMagnificationEnabled);
-                pw.append(", autoclickEnabled=" + userState.mIsAutoclickEnabled);
-                pw.append(", nonInteractiveUiTimeout=" + userState.mNonInteractiveUiTimeout);
-                pw.append(", interactiveUiTimeout=" + userState.mInteractiveUiTimeout);
-                pw.append(", installedServiceCount=" + userState.mInstalledServices.size());
-                if (mUiAutomationManager.isUiAutomationRunningLocked()) {
-                    pw.append(", ");
-                    mUiAutomationManager.dumpUiAutomationService(fd, pw, args);
-                    pw.println();
-                }
-                pw.append("}");
-                pw.println();
-                pw.append("     Bound services:{");
-                final int serviceCount = userState.mBoundServices.size();
-                for (int j = 0; j < serviceCount; j++) {
-                    if (j > 0) {
-                        pw.append(", ");
-                        pw.println();
-                        pw.append("                     ");
-                    }
-                    AccessibilityServiceConnection service = userState.mBoundServices.get(j);
-                    service.dump(fd, pw, args);
-                }
-                pw.println("}");
-                pw.append("     Enabled services:{");
-                Iterator<ComponentName> it = userState.mEnabledServices.iterator();
-                if (it.hasNext()) {
-                    ComponentName componentName = it.next();
-                    pw.append(componentName.toShortString());
-                    while (it.hasNext()) {
-                        componentName = it.next();
-                        pw.append(", ");
-                        pw.append(componentName.toShortString());
-                    }
-                }
-                pw.println("}");
-                pw.append("     Binding services:{");
-                it = userState.mBindingServices.iterator();
-                if (it.hasNext()) {
-                    ComponentName componentName = it.next();
-                    pw.append(componentName.toShortString());
-                    while (it.hasNext()) {
-                        componentName = it.next();
-                        pw.append(", ");
-                        pw.append(componentName.toShortString());
-                    }
-                }
-                pw.println("}]");
+                mUserStates.valueAt(i).dump(fd, pw, args);
+            }
+            if (mUiAutomationManager.isUiAutomationRunningLocked()) {
+                mUiAutomationManager.dumpUiAutomationService(fd, pw, args);
                 pw.println();
             }
             mA11yWindowManager.dump(fd, pw, args);
         }
     }
 
-    private void putSecureIntForUser(String key, int value, int userid) {
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            Settings.Secure.putIntForUser(mContext.getContentResolver(), key, value, userid);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
     //TODO remove after refactoring KeyEventDispatcherTest
     final class MainHandler extends Handler {
         public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8;
@@ -2446,7 +2377,7 @@
 
     @Override
     public void onClientChangeLocked(boolean serviceInfoChanged) {
-        AccessibilityManagerService.UserState userState = getUserStateLocked(mCurrentUserId);
+        AccessibilityUserState userState = getUserStateLocked(mCurrentUserId);
         onUserStateChangedLocked(userState);
         if (serviceInfoChanged) {
             scheduleNotifyClientsOfServicesStateChangeLocked(userState);
@@ -2474,7 +2405,7 @@
             info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
             info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
             info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
-            final UserState userState;
+            final AccessibilityUserState userState;
             synchronized (mLock) {
                 userState = getCurrentUserStateLocked();
             }
@@ -2593,7 +2524,7 @@
                 if (mInputFilter != null) {
                     mInputFilter.onDisplayChanged();
                 }
-                UserState userState = getCurrentUserStateLocked();
+                AccessibilityUserState userState = getCurrentUserStateLocked();
                 if (displayId != Display.DEFAULT_DISPLAY) {
                     final List<AccessibilityServiceConnection> services = userState.mBoundServices;
                     for (int i = 0; i < services.size(); i++) {
@@ -2618,7 +2549,7 @@
                 if (mInputFilter != null) {
                     mInputFilter.onDisplayChanged();
                 }
-                UserState userState = getCurrentUserStateLocked();
+                AccessibilityUserState userState = getCurrentUserStateLocked();
                 if (displayId != Display.DEFAULT_DISPLAY) {
                     final List<AccessibilityServiceConnection> services = userState.mBoundServices;
                     for (int i = 0; i < services.size(); i++) {
@@ -2658,7 +2589,8 @@
         final String[] mPackageNames;
         int mLastSentRelevantEventTypes;
 
-        private Client(IAccessibilityManagerClient callback, int clientUid, UserState userState) {
+        private Client(IAccessibilityManagerClient callback, int clientUid,
+                AccessibilityUserState userState) {
             mCallback = callback;
             mPackageNames = mPackageManager.getPackagesForUid(clientUid);
             synchronized (mLock) {
@@ -2667,316 +2599,6 @@
         }
     }
 
-    public class UserState {
-        public final int mUserId;
-
-        // Non-transient state.
-
-        public final RemoteCallbackList<IAccessibilityManagerClient> mUserClients =
-                new RemoteCallbackList<>();
-
-        // Transient state.
-
-        public final ArrayList<AccessibilityServiceConnection> mBoundServices = new ArrayList<>();
-
-        public final Map<ComponentName, AccessibilityServiceConnection> mComponentNameToServiceMap =
-                new HashMap<>();
-
-        public final List<AccessibilityServiceInfo> mInstalledServices =
-                new ArrayList<>();
-
-        public final List<AccessibilityShortcutInfo> mInstalledShortcuts = new ArrayList<>();
-
-        private final Set<ComponentName> mBindingServices = new HashSet<>();
-
-        public final Set<ComponentName> mEnabledServices = new HashSet<>();
-
-        public final Set<ComponentName> mTouchExplorationGrantedServices =
-                new HashSet<>();
-
-        public ComponentName mServiceChangingSoftKeyboardMode;
-
-        public ComponentName mServiceToEnableWithShortcut;
-
-        public int mLastSentClientState = -1;
-        public int mNonInteractiveUiTimeout = 0;
-        public int mInteractiveUiTimeout = 0;
-
-        private int mSoftKeyboardShowMode = 0;
-
-        public boolean mIsNavBarMagnificationAssignedToAccessibilityButton;
-        public ComponentName mServiceAssignedToAccessibilityButton;
-
-        public boolean mIsTouchExplorationEnabled;
-        public boolean mIsTextHighContrastEnabled;
-        public boolean mIsDisplayMagnificationEnabled;
-        public boolean mIsNavBarMagnificationEnabled;
-        public boolean mIsAutoclickEnabled;
-        public boolean mIsPerformGesturesEnabled;
-        public boolean mIsFilterKeyEventsEnabled;
-        public int mUserNonInteractiveUiTimeout;
-        public int mUserInteractiveUiTimeout;
-
-        private boolean mBindInstantServiceAllowed;
-
-        public UserState(int userId) {
-            mUserId = userId;
-        }
-
-        public int getClientState() {
-            int clientState = 0;
-            final boolean a11yEnabled = (mUiAutomationManager.isUiAutomationRunningLocked()
-                    || isHandlingAccessibilityEvents());
-            if (a11yEnabled) {
-                clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
-            }
-            // Touch exploration relies on enabled accessibility.
-            if (a11yEnabled && mIsTouchExplorationEnabled) {
-                clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
-            }
-            if (mIsTextHighContrastEnabled) {
-                clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
-            }
-            return clientState;
-        }
-
-        public boolean isHandlingAccessibilityEvents() {
-            return !mBoundServices.isEmpty() || !mBindingServices.isEmpty();
-        }
-
-        public void onSwitchToAnotherUserLocked() {
-            // Unbind all services.
-            unbindAllServicesLocked(this);
-
-            // Clear service management state.
-            mBoundServices.clear();
-            mBindingServices.clear();
-
-            // Clear event management state.
-            mLastSentClientState = -1;
-
-            // clear UI timeout
-            mNonInteractiveUiTimeout = 0;
-            mInteractiveUiTimeout = 0;
-
-            // Clear state persisted in settings.
-            mEnabledServices.clear();
-            mTouchExplorationGrantedServices.clear();
-            mIsTouchExplorationEnabled = false;
-            mIsDisplayMagnificationEnabled = false;
-            mIsNavBarMagnificationEnabled = false;
-            mServiceAssignedToAccessibilityButton = null;
-            mIsNavBarMagnificationAssignedToAccessibilityButton = false;
-            mIsAutoclickEnabled = false;
-            mUserNonInteractiveUiTimeout = 0;
-            mUserInteractiveUiTimeout = 0;
-        }
-
-        public void addServiceLocked(AccessibilityServiceConnection serviceConnection) {
-            if (!mBoundServices.contains(serviceConnection)) {
-                serviceConnection.onAdded();
-                mBoundServices.add(serviceConnection);
-                mComponentNameToServiceMap.put(serviceConnection.mComponentName, serviceConnection);
-                scheduleNotifyClientsOfServicesStateChangeLocked(this);
-            }
-        }
-
-        /**
-         * Removes a service.
-         * There are three states to a service here: off, bound, and binding.
-         * This stops tracking the service as bound.
-         *
-         * @param serviceConnection The service.
-         */
-        public void removeServiceLocked(AccessibilityServiceConnection serviceConnection) {
-            mBoundServices.remove(serviceConnection);
-            serviceConnection.onRemoved();
-            if ((mServiceChangingSoftKeyboardMode != null)
-                    && (mServiceChangingSoftKeyboardMode.equals(
-                            serviceConnection.getServiceInfo().getComponentName()))) {
-                setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
-            }
-            // It may be possible to bind a service twice, which confuses the map. Rebuild the map
-            // to make sure we can still reach a service
-            mComponentNameToServiceMap.clear();
-            for (int i = 0; i < mBoundServices.size(); i++) {
-                AccessibilityServiceConnection boundClient = mBoundServices.get(i);
-                mComponentNameToServiceMap.put(boundClient.mComponentName, boundClient);
-            }
-            scheduleNotifyClientsOfServicesStateChangeLocked(this);
-        }
-
-        /**
-         * Make sure a services disconnected but still 'on' state is reflected in UserState
-         * There are three states to a service here: off, bound, and binding.
-         * This drops a service from a bound state, to the binding state.
-         * The binding state describes the situation where a service is on, but not bound.
-         *
-         * @param serviceConnection The service.
-         */
-        public void serviceDisconnectedLocked(AccessibilityServiceConnection serviceConnection) {
-            removeServiceLocked(serviceConnection);
-            mBindingServices.add(serviceConnection.getComponentName());
-        }
-
-        public Set<ComponentName> getBindingServicesLocked() {
-            return mBindingServices;
-        }
-
-        /**
-         * Returns enabled service list.
-         */
-        public Set<ComponentName> getEnabledServicesLocked() {
-            return mEnabledServices;
-        }
-
-        public int getSoftKeyboardShowMode() {
-            return mSoftKeyboardShowMode;
-        }
-
-        /**
-         * Set the soft keyboard mode. This mode is a bit odd, as it spans multiple settings.
-         * The ACCESSIBILITY_SOFT_KEYBOARD_MODE setting can be checked by the rest of the system
-         * to see if it should suppress showing the IME. The SHOW_IME_WITH_HARD_KEYBOARD setting
-         * setting can be changed by the user, and prevents the system from suppressing the soft
-         * keyboard when the hard keyboard is connected. The hard keyboard setting needs to defer
-         * to the user's preference, if they have supplied one.
-         *
-         * @param newMode The new mode
-         * @param requester The service requesting the change, so we can undo it when the
-         *                  service stops. Set to null if something other than a service is forcing
-         *                  the change.
-         *
-         * @return Whether or not the soft keyboard mode equals the new mode after the call
-         */
-        public boolean setSoftKeyboardModeLocked(int newMode, @Nullable ComponentName requester) {
-            if ((newMode != SHOW_MODE_AUTO) && (newMode != SHOW_MODE_HIDDEN)
-                    && (newMode != SHOW_MODE_IGNORE_HARD_KEYBOARD))
-            {
-                Slog.w(LOG_TAG, "Invalid soft keyboard mode");
-                return false;
-            }
-            if (mSoftKeyboardShowMode == newMode) return true;
-
-            if (newMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) {
-                if (hasUserOverriddenHardKeyboardSettingLocked()) {
-                    // The user has specified a default for this setting
-                    return false;
-                }
-                // Save the original value. But don't do this if the value in settings is already
-                // the new mode. That happens when we start up after a reboot, and we don't want
-                // to overwrite the value we had from when we first started controlling the setting.
-                if (getSoftKeyboardValueFromSettings() != SHOW_MODE_IGNORE_HARD_KEYBOARD) {
-                    setOriginalHardKeyboardValue(
-                            Settings.Secure.getInt(mContext.getContentResolver(),
-                                    Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0);
-                }
-                putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 1, mUserId);
-            } else if (mSoftKeyboardShowMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) {
-                putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
-                        getOriginalHardKeyboardValue() ? 1 : 0, mUserId);
-            }
-
-            saveSoftKeyboardValueToSettings(newMode);
-            mSoftKeyboardShowMode = newMode;
-            mServiceChangingSoftKeyboardMode = requester;
-            notifySoftKeyboardShowModeChangedLocked(mSoftKeyboardShowMode);
-            return true;
-        }
-
-        /**
-         * If the settings are inconsistent with the internal state, make the internal state
-         * match the settings.
-         */
-        public void reconcileSoftKeyboardModeWithSettingsLocked() {
-            final ContentResolver cr = mContext.getContentResolver();
-            final boolean showWithHardKeyboardSettings =
-                    Settings.Secure.getInt(cr, Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0;
-            if (mSoftKeyboardShowMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) {
-                if (!showWithHardKeyboardSettings) {
-                    // The user has overridden the setting. Respect that and prevent further changes
-                    // to this behavior.
-                    setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
-                    setUserOverridesHardKeyboardSettingLocked();
-                }
-            }
-
-            // If the setting and the internal state are out of sync, set both to default
-            if (getSoftKeyboardValueFromSettings() != mSoftKeyboardShowMode)
-            {
-                Slog.e(LOG_TAG,
-                        "Show IME setting inconsistent with internal state. Overwriting");
-                setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
-                putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
-                        SHOW_MODE_AUTO, mUserId);
-            }
-        }
-
-        private void setUserOverridesHardKeyboardSettingLocked() {
-            final int softKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
-            putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
-                    softKeyboardSetting | SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN,
-                    mUserId);
-        }
-
-        private boolean hasUserOverriddenHardKeyboardSettingLocked() {
-            final int softKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
-            return (softKeyboardSetting & SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN)
-                    != 0;
-        }
-
-        private void setOriginalHardKeyboardValue(boolean originalHardKeyboardValue) {
-            final int oldSoftKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
-            final int newSoftKeyboardSetting = oldSoftKeyboardSetting
-                    & (~SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE)
-                    | ((originalHardKeyboardValue) ? SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE : 0);
-            putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
-                    newSoftKeyboardSetting, mUserId);
-        }
-
-        private void saveSoftKeyboardValueToSettings(int softKeyboardShowMode) {
-            final int oldSoftKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
-            final int newSoftKeyboardSetting = oldSoftKeyboardSetting & (~SHOW_MODE_MASK)
-                    | softKeyboardShowMode;
-            putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
-                    newSoftKeyboardSetting, mUserId);
-        }
-
-        private int getSoftKeyboardValueFromSettings() {
-            return Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
-                    SHOW_MODE_AUTO) & SHOW_MODE_MASK;
-        }
-
-        private boolean getOriginalHardKeyboardValue() {
-            return (Settings.Secure.getInt(mContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0)
-                    & SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE) != 0;
-        }
-
-        public boolean getBindInstantServiceAllowed() {
-            synchronized (mLock) {
-                return mBindInstantServiceAllowed;
-            }
-        }
-
-        public void setBindInstantServiceAllowed(boolean allowed) {
-            synchronized (mLock) {
-                mContext.enforceCallingOrSelfPermission(
-                        Manifest.permission.MANAGE_BIND_INSTANT_SERVICE,
-                        "setBindInstantServiceAllowed");
-                if (allowed) {
-                    mBindInstantServiceAllowed = allowed;
-                    onUserStateChangedLocked(this);
-                }
-            }
-        }
-    }
-
     private final class AccessibilityContentObserver extends ContentObserver {
 
         private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
@@ -3057,7 +2679,7 @@
             synchronized (mLock) {
                 // Profiles share the accessibility state of the parent. Therefore,
                 // we are checking for changes only the parent settings.
-                UserState userState = getCurrentUserStateLocked();
+                AccessibilityUserState userState = getCurrentUserStateLocked();
 
                 if (mTouchExplorationEnabledUri.equals(uri)) {
                     if (readTouchExplorationEnabledSettingLocked(userState)) {
@@ -3074,6 +2696,7 @@
                     }
                 } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
                     if (readEnabledAccessibilityServicesLocked(userState)) {
+                        userState.updateCrashedServicesIfNeededLocked();
                         onUserStateChangedLocked(userState);
                     }
                 } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index e7f3ccc..a0a755a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -35,7 +35,6 @@
 import android.util.Slog;
 import android.view.Display;
 
-import com.android.server.accessibility.AccessibilityManagerService.UserState;
 import com.android.server.wm.WindowManagerInternal;
 
 import java.lang.ref.WeakReference;
@@ -52,21 +51,18 @@
 class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnection {
     private static final String LOG_TAG = "AccessibilityServiceConnection";
     /*
-     Holding a weak reference so there isn't a loop of references. UserState keeps lists of bound
-     and binding services. These are freed on user changes, but just in case it somehow gets lost
-     the weak reference will let the memory get GCed.
+     Holding a weak reference so there isn't a loop of references. AccessibilityUserState keeps
+     lists of bound and binding services. These are freed on user changes, but just in case it
+     somehow gets lost the weak reference will let the memory get GCed.
 
      Having the reference be null when being called is a very bad sign, but we check the condition.
     */
-    final WeakReference<UserState> mUserStateWeakReference;
+    final WeakReference<AccessibilityUserState> mUserStateWeakReference;
     final Intent mIntent;
 
     private final Handler mMainHandler;
 
-    private boolean mWasConnectedAndDied;
-
-
-    public AccessibilityServiceConnection(UserState userState, Context context,
+    AccessibilityServiceConnection(AccessibilityUserState userState, Context context,
             ComponentName componentName,
             AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler,
             Object lock, AccessibilitySecurityPolicy securityPolicy, SystemSupport systemSupport,
@@ -74,7 +70,7 @@
             SystemActionPerformer systemActionPerfomer, AccessibilityWindowManager awm) {
         super(context, componentName, accessibilityServiceInfo, id, mainHandler, lock,
                 securityPolicy, systemSupport, windowManagerInternal, systemActionPerfomer, awm);
-        mUserStateWeakReference = new WeakReference<UserState>(userState);
+        mUserStateWeakReference = new WeakReference<AccessibilityUserState>(userState);
         mIntent = new Intent().setComponent(mComponentName);
         mMainHandler = mainHandler;
         mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
@@ -89,13 +85,13 @@
     }
 
     public void bindLocked() {
-        UserState userState = mUserStateWeakReference.get();
+        AccessibilityUserState userState = mUserStateWeakReference.get();
         if (userState == null) return;
         final long identity = Binder.clearCallingIdentity();
         try {
             int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE
                     | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS;
-            if (userState.getBindInstantServiceAllowed()) {
+            if (userState.getBindInstantServiceAllowedLocked()) {
                 flags |= Context.BIND_ALLOW_INSTANT;
             }
             if (mService == null && mContext.bindServiceAsUser(
@@ -109,7 +105,7 @@
 
     public void unbindLocked() {
         mContext.unbindService(this);
-        UserState userState = mUserStateWeakReference.get();
+        AccessibilityUserState userState = mUserStateWeakReference.get();
         if (userState == null) return;
         userState.removeServiceLocked(this);
         mSystemSupport.getMagnificationController().resetAllIfNeeded(mId);
@@ -123,7 +119,7 @@
     @Override
     public void disableSelf() {
         synchronized (mLock) {
-            UserState userState = mUserStateWeakReference.get();
+            AccessibilityUserState userState = mUserStateWeakReference.get();
             if (userState == null) return;
             if (userState.getEnabledServicesLocked().remove(mComponentName)) {
                 final long identity = Binder.clearCallingIdentity();
@@ -156,7 +152,7 @@
                 }
             }
             mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service);
-            UserState userState = mUserStateWeakReference.get();
+            AccessibilityUserState userState = mUserStateWeakReference.get();
             if (userState == null) return;
             userState.addServiceLocked(this);
             mSystemSupport.onClientChangeLocked(false);
@@ -169,20 +165,21 @@
 
     @Override
     public AccessibilityServiceInfo getServiceInfo() {
-        // Update crashed data
-        mAccessibilityServiceInfo.crashed = mWasConnectedAndDied;
         return mAccessibilityServiceInfo;
     }
 
     private void initializeService() {
         IAccessibilityServiceClient serviceInterface = null;
         synchronized (mLock) {
-            UserState userState = mUserStateWeakReference.get();
+            AccessibilityUserState userState = mUserStateWeakReference.get();
             if (userState == null) return;
-            Set<ComponentName> bindingServices = userState.getBindingServicesLocked();
-            if (bindingServices.contains(mComponentName) || mWasConnectedAndDied) {
+            final Set<ComponentName> bindingServices = userState.getBindingServicesLocked();
+            final Set<ComponentName> crashedServices = userState.getCrashedServicesLocked();
+            if (bindingServices.contains(mComponentName)
+                    || crashedServices.contains(mComponentName)) {
                 bindingServices.remove(mComponentName);
-                mWasConnectedAndDied = false;
+                crashedServices.remove(mComponentName);
+                mAccessibilityServiceInfo.crashed = false;
                 serviceInterface = mServiceInterface;
             }
             // There's a chance that service is removed from enabled_accessibility_services setting
@@ -240,7 +237,7 @@
             if (!hasRightsToCurrentUserLocked()) {
                 return false;
             }
-            final UserState userState = mUserStateWeakReference.get();
+            final AccessibilityUserState userState = mUserStateWeakReference.get();
             if (userState == null) return false;
             return userState.setSoftKeyboardModeLocked(showMode, mComponentName);
         }
@@ -248,8 +245,8 @@
 
     @Override
     public int getSoftKeyboardShowMode() {
-        final UserState userState = mUserStateWeakReference.get();
-        return (userState != null) ? userState.getSoftKeyboardShowMode() : 0;
+        final AccessibilityUserState userState = mUserStateWeakReference.get();
+        return (userState != null) ? userState.getSoftKeyboardShowModeLocked() : 0;
     }
 
     @Override
@@ -258,7 +255,7 @@
             if (!hasRightsToCurrentUserLocked()) {
                 return false;
             }
-            UserState userState = mUserStateWeakReference.get();
+            AccessibilityUserState userState = mUserStateWeakReference.get();
             return (userState != null) && isAccessibilityButtonAvailableLocked(userState);
         }
     }
@@ -272,8 +269,8 @@
             if (!isConnectedLocked()) {
                 return;
             }
-            mWasConnectedAndDied = true;
-            UserState userState = mUserStateWeakReference.get();
+            mAccessibilityServiceInfo.crashed = true;
+            AccessibilityUserState userState = mUserStateWeakReference.get();
             if (userState != null) {
                 userState.serviceDisconnectedLocked(this);
             }
@@ -283,7 +280,7 @@
         }
     }
 
-    public boolean isAccessibilityButtonAvailableLocked(UserState userState) {
+    public boolean isAccessibilityButtonAvailableLocked(AccessibilityUserState userState) {
         // If the service does not request the accessibility button, it isn't available
         if (!mRequestAccessibilityButton) {
             return false;
@@ -295,8 +292,8 @@
         }
 
         // If magnification is on and assigned to the accessibility button, services cannot be
-        if (userState.mIsNavBarMagnificationEnabled
-                && userState.mIsNavBarMagnificationAssignedToAccessibilityButton) {
+        if (userState.isNavBarMagnificationEnabledLocked()
+                && userState.isNavBarMagnificationAssignedToAccessibilityButtonLocked()) {
             return false;
         }
 
@@ -314,13 +311,14 @@
             return true;
         } else {
             // With more than one active service, we derive the target from the user's settings
-            if (userState.mServiceAssignedToAccessibilityButton == null) {
+            if (userState.getServiceAssignedToAccessibilityButtonLocked() == null) {
                 // If the user has not made an assignment, we treat the button as available to
                 // all services until the user interacts with the button to make an assignment
                 return true;
             } else {
                 // If an assignment was made, it defines availability
-                return mComponentName.equals(userState.mServiceAssignedToAccessibilityButton);
+                return mComponentName.equals(
+                        userState.getServiceAssignedToAccessibilityButtonLocked());
             }
         }
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
new file mode 100644
index 0000000..a0b9866
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -0,0 +1,616 @@
+/*
+ * 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.server.accessibility;
+
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_AUTO;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_IGNORE_HARD_KEYBOARD;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_MASK;
+
+import android.accessibilityservice.AccessibilityService.SoftKeyboardShowMode;
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.AccessibilityShortcutInfo;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Binder;
+import android.os.RemoteCallbackList;
+import android.provider.Settings;
+import android.util.Slog;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.IAccessibilityManagerClient;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Class that hold states and settings per user and share between
+ * {@link AccessibilityManagerService} and {@link AccessibilityServiceConnection}.
+ */
+class AccessibilityUserState {
+    private static final String LOG_TAG = AccessibilityUserState.class.getSimpleName();
+
+    final int mUserId;
+
+    // Non-transient state.
+
+    final RemoteCallbackList<IAccessibilityManagerClient> mUserClients = new RemoteCallbackList<>();
+
+    // Transient state.
+
+    final ArrayList<AccessibilityServiceConnection> mBoundServices = new ArrayList<>();
+
+    final Map<ComponentName, AccessibilityServiceConnection> mComponentNameToServiceMap =
+            new HashMap<>();
+
+    final List<AccessibilityServiceInfo> mInstalledServices = new ArrayList<>();
+
+    final List<AccessibilityShortcutInfo> mInstalledShortcuts = new ArrayList<>();
+
+    final Set<ComponentName> mBindingServices = new HashSet<>();
+
+    final Set<ComponentName> mCrashedServices = new HashSet<>();
+
+    final Set<ComponentName> mEnabledServices = new HashSet<>();
+
+    final Set<ComponentName> mTouchExplorationGrantedServices = new HashSet<>();
+
+    private final ServiceInfoChangeListener mServiceInfoChangeListener;
+
+    private ComponentName mServiceAssignedToAccessibilityButton;
+
+    private ComponentName mServiceChangingSoftKeyboardMode;
+
+    private ComponentName mServiceToEnableWithShortcut;
+
+    private boolean mBindInstantServiceAllowed;
+    private boolean mIsAutoclickEnabled;
+    private boolean mIsDisplayMagnificationEnabled;
+    private boolean mIsFilterKeyEventsEnabled;
+    private boolean mIsNavBarMagnificationAssignedToAccessibilityButton;
+    private boolean mIsNavBarMagnificationEnabled;
+    private boolean mIsPerformGesturesEnabled;
+    private boolean mIsTextHighContrastEnabled;
+    private boolean mIsTouchExplorationEnabled;
+    private int mUserInteractiveUiTimeout;
+    private int mUserNonInteractiveUiTimeout;
+    private int mNonInteractiveUiTimeout = 0;
+    private int mInteractiveUiTimeout = 0;
+    private int mLastSentClientState = -1;
+
+    private Context mContext;
+
+    @SoftKeyboardShowMode
+    private int mSoftKeyboardShowMode = SHOW_MODE_AUTO;
+
+    interface ServiceInfoChangeListener {
+        void onServiceInfoChangedLocked(AccessibilityUserState userState);
+    }
+
+    AccessibilityUserState(int userId, @NonNull Context context,
+            @NonNull ServiceInfoChangeListener serviceInfoChangeListener) {
+        mUserId = userId;
+        mContext = context;
+        mServiceInfoChangeListener = serviceInfoChangeListener;
+    }
+
+    boolean isHandlingAccessibilityEventsLocked() {
+        return !mBoundServices.isEmpty() || !mBindingServices.isEmpty();
+    }
+
+    void onSwitchToAnotherUserLocked() {
+        // Unbind all services.
+        unbindAllServicesLocked();
+
+        // Clear service management state.
+        mBoundServices.clear();
+        mBindingServices.clear();
+        mCrashedServices.clear();
+
+        // Clear event management state.
+        mLastSentClientState = -1;
+
+        // clear UI timeout
+        mNonInteractiveUiTimeout = 0;
+        mInteractiveUiTimeout = 0;
+
+        // Clear state persisted in settings.
+        mEnabledServices.clear();
+        mTouchExplorationGrantedServices.clear();
+        mIsTouchExplorationEnabled = false;
+        mIsDisplayMagnificationEnabled = false;
+        mIsNavBarMagnificationEnabled = false;
+        mServiceAssignedToAccessibilityButton = null;
+        mIsNavBarMagnificationAssignedToAccessibilityButton = false;
+        mIsAutoclickEnabled = false;
+        mUserNonInteractiveUiTimeout = 0;
+        mUserInteractiveUiTimeout = 0;
+    }
+
+    void addServiceLocked(AccessibilityServiceConnection serviceConnection) {
+        if (!mBoundServices.contains(serviceConnection)) {
+            serviceConnection.onAdded();
+            mBoundServices.add(serviceConnection);
+            mComponentNameToServiceMap.put(serviceConnection.getComponentName(), serviceConnection);
+            mServiceInfoChangeListener.onServiceInfoChangedLocked(this);
+        }
+    }
+
+    /**
+     * Removes a service.
+     * There are three states to a service here: off, bound, and binding.
+     * This stops tracking the service as bound.
+     *
+     * @param serviceConnection The service.
+     */
+    void removeServiceLocked(AccessibilityServiceConnection serviceConnection) {
+        mBoundServices.remove(serviceConnection);
+        serviceConnection.onRemoved();
+        if ((mServiceChangingSoftKeyboardMode != null)
+                && (mServiceChangingSoftKeyboardMode.equals(
+                serviceConnection.getServiceInfo().getComponentName()))) {
+            setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
+        }
+        // It may be possible to bind a service twice, which confuses the map. Rebuild the map
+        // to make sure we can still reach a service
+        mComponentNameToServiceMap.clear();
+        for (int i = 0; i < mBoundServices.size(); i++) {
+            AccessibilityServiceConnection boundClient = mBoundServices.get(i);
+            mComponentNameToServiceMap.put(boundClient.getComponentName(), boundClient);
+        }
+        mServiceInfoChangeListener.onServiceInfoChangedLocked(this);
+    }
+
+    /**
+     * Make sure a services disconnected but still 'on' state is reflected in AccessibilityUserState
+     * There are four states to a service here: off, bound, and binding, and crashed.
+     * This drops a service from a bound state, to the crashed state.
+     * The crashed state describes the situation where a service used to be bound, but no longer is
+     * despite still being enabled.
+     *
+     * @param serviceConnection The service.
+     */
+    void serviceDisconnectedLocked(AccessibilityServiceConnection serviceConnection) {
+        removeServiceLocked(serviceConnection);
+        mCrashedServices.add(serviceConnection.getComponentName());
+    }
+
+    /**
+     * Set the soft keyboard mode. This mode is a bit odd, as it spans multiple settings.
+     * The ACCESSIBILITY_SOFT_KEYBOARD_MODE setting can be checked by the rest of the system
+     * to see if it should suppress showing the IME. The SHOW_IME_WITH_HARD_KEYBOARD setting
+     * setting can be changed by the user, and prevents the system from suppressing the soft
+     * keyboard when the hard keyboard is connected. The hard keyboard setting needs to defer
+     * to the user's preference, if they have supplied one.
+     *
+     * @param newMode The new mode
+     * @param requester The service requesting the change, so we can undo it when the
+     *                  service stops. Set to null if something other than a service is forcing
+     *                  the change.
+     *
+     * @return Whether or not the soft keyboard mode equals the new mode after the call
+     */
+    boolean setSoftKeyboardModeLocked(@SoftKeyboardShowMode int newMode,
+            @Nullable ComponentName requester) {
+        if ((newMode != SHOW_MODE_AUTO)
+                && (newMode != SHOW_MODE_HIDDEN)
+                && (newMode != SHOW_MODE_IGNORE_HARD_KEYBOARD)) {
+            Slog.w(LOG_TAG, "Invalid soft keyboard mode");
+            return false;
+        }
+        if (mSoftKeyboardShowMode == newMode) {
+            return true;
+        }
+
+        if (newMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) {
+            if (hasUserOverriddenHardKeyboardSetting()) {
+                // The user has specified a default for this setting
+                return false;
+            }
+            // Save the original value. But don't do this if the value in settings is already
+            // the new mode. That happens when we start up after a reboot, and we don't want
+            // to overwrite the value we had from when we first started controlling the setting.
+            if (getSoftKeyboardValueFromSettings() != SHOW_MODE_IGNORE_HARD_KEYBOARD) {
+                setOriginalHardKeyboardValue(getSecureIntForUser(
+                        Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0, mUserId) != 0);
+            }
+            putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 1, mUserId);
+        } else if (mSoftKeyboardShowMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) {
+            putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
+                    getOriginalHardKeyboardValue() ? 1 : 0, mUserId);
+        }
+
+        saveSoftKeyboardValueToSettings(newMode);
+        mSoftKeyboardShowMode = newMode;
+        mServiceChangingSoftKeyboardMode = requester;
+        for (int i = mBoundServices.size() - 1; i >= 0; i--) {
+            final AccessibilityServiceConnection service = mBoundServices.get(i);
+            service.notifySoftKeyboardShowModeChangedLocked(mSoftKeyboardShowMode);
+        }
+        return true;
+    }
+
+    @SoftKeyboardShowMode
+    int getSoftKeyboardShowModeLocked() {
+        return mSoftKeyboardShowMode;
+    }
+
+    /**
+     * If the settings are inconsistent with the internal state, make the internal state
+     * match the settings.
+     */
+    void reconcileSoftKeyboardModeWithSettingsLocked() {
+        final boolean showWithHardKeyboardSettings =
+                getSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0, mUserId) != 0;
+        if (mSoftKeyboardShowMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) {
+            if (!showWithHardKeyboardSettings) {
+                // The user has overridden the setting. Respect that and prevent further changes
+                // to this behavior.
+                setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
+                setUserOverridesHardKeyboardSetting();
+            }
+        }
+
+        // If the setting and the internal state are out of sync, set both to default
+        if (getSoftKeyboardValueFromSettings() != mSoftKeyboardShowMode) {
+            Slog.e(LOG_TAG, "Show IME setting inconsistent with internal state. Overwriting");
+            setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
+            putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                    SHOW_MODE_AUTO, mUserId);
+        }
+    }
+
+    boolean getBindInstantServiceAllowedLocked() {
+        return mBindInstantServiceAllowed;
+    }
+
+    /* Need to have a permission check on callee */
+    void setBindInstantServiceAllowedLocked(boolean allowed) {
+        mBindInstantServiceAllowed = allowed;
+    }
+
+    /**
+     * Returns binding service list.
+     */
+    Set<ComponentName> getBindingServicesLocked() {
+        return mBindingServices;
+    }
+
+    /**
+     * Returns crashed service list.
+     */
+    Set<ComponentName> getCrashedServicesLocked() {
+        return mCrashedServices;
+    }
+
+    /**
+     * Returns enabled service list.
+     */
+    Set<ComponentName> getEnabledServicesLocked() {
+        return mEnabledServices;
+    }
+
+    /**
+     * Remove service from crashed service list if users disable it.
+     */
+    void updateCrashedServicesIfNeededLocked() {
+        for (int i = 0, count = mInstalledServices.size(); i < count; i++) {
+            final AccessibilityServiceInfo installedService = mInstalledServices.get(i);
+            final ComponentName componentName = ComponentName.unflattenFromString(
+                    installedService.getId());
+
+            if (mCrashedServices.contains(componentName)
+                    && !mEnabledServices.contains(componentName)) {
+                // Remove it from mCrashedServices since users toggle the switch bar to retry.
+                mCrashedServices.remove(componentName);
+            }
+        }
+    }
+
+    List<AccessibilityServiceConnection> getBoundServicesLocked() {
+        return mBoundServices;
+    }
+
+    int getClientStateLocked(boolean isUiAutomationRunning) {
+        int clientState = 0;
+        final boolean a11yEnabled = isUiAutomationRunning
+                || isHandlingAccessibilityEventsLocked();
+        if (a11yEnabled) {
+            clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
+        }
+        // Touch exploration relies on enabled accessibility.
+        if (a11yEnabled && mIsTouchExplorationEnabled) {
+            clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
+        }
+        if (mIsTextHighContrastEnabled) {
+            clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
+        }
+        return clientState;
+    }
+
+    private void setUserOverridesHardKeyboardSetting() {
+        final int softKeyboardSetting = getSecureIntForUser(
+                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, SHOW_MODE_AUTO, mUserId);
+        putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                softKeyboardSetting | SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN,
+                mUserId);
+    }
+
+    private boolean hasUserOverriddenHardKeyboardSetting() {
+        final int softKeyboardSetting = getSecureIntForUser(
+                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, SHOW_MODE_AUTO, mUserId);
+        return (softKeyboardSetting & SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN)
+                != 0;
+    }
+
+    private void setOriginalHardKeyboardValue(boolean originalHardKeyboardValue) {
+        final int oldSoftKeyboardSetting = getSecureIntForUser(
+                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, SHOW_MODE_AUTO, mUserId);
+        final int newSoftKeyboardSetting = oldSoftKeyboardSetting
+                & (~SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE)
+                | ((originalHardKeyboardValue) ? SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE : 0);
+        putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                newSoftKeyboardSetting, mUserId);
+    }
+
+    private void saveSoftKeyboardValueToSettings(int softKeyboardShowMode) {
+        final int oldSoftKeyboardSetting = getSecureIntForUser(
+                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, SHOW_MODE_AUTO, mUserId);
+        final int newSoftKeyboardSetting = oldSoftKeyboardSetting & (~SHOW_MODE_MASK)
+                | softKeyboardShowMode;
+        putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                newSoftKeyboardSetting, mUserId);
+    }
+
+    private int getSoftKeyboardValueFromSettings() {
+        return getSecureIntForUser(
+                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, SHOW_MODE_AUTO, mUserId)
+                & SHOW_MODE_MASK;
+    }
+
+    private boolean getOriginalHardKeyboardValue() {
+        return (getSecureIntForUser(
+                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, SHOW_MODE_AUTO, mUserId)
+                & SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE) != 0;
+    }
+
+    private void unbindAllServicesLocked() {
+        final List<AccessibilityServiceConnection> services = mBoundServices;
+        for (int count = services.size(); count > 0; count--) {
+            // When the service is unbound, it disappears from the list, so there's no need to
+            // keep track of the index
+            services.get(0).unbindLocked();
+        }
+    }
+
+    private int getSecureIntForUser(String key, int def, int userId) {
+        return Settings.Secure.getIntForUser(mContext.getContentResolver(), key, def, userId);
+    }
+
+    private void putSecureIntForUser(String key, int value, int userId) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            Settings.Secure.putIntForUser(mContext.getContentResolver(), key, value, userId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.append("User state[");
+        pw.println();
+        pw.append("     attributes:{id=").append(String.valueOf(mUserId));
+        pw.append(", touchExplorationEnabled=").append(String.valueOf(mIsTouchExplorationEnabled));
+        pw.append(", displayMagnificationEnabled=").append(String.valueOf(
+                mIsDisplayMagnificationEnabled));
+        pw.append(", navBarMagnificationEnabled=").append(String.valueOf(
+                mIsNavBarMagnificationEnabled));
+        pw.append(", autoclickEnabled=").append(String.valueOf(mIsAutoclickEnabled));
+        pw.append(", nonInteractiveUiTimeout=").append(String.valueOf(mNonInteractiveUiTimeout));
+        pw.append(", interactiveUiTimeout=").append(String.valueOf(mInteractiveUiTimeout));
+        pw.append(", installedServiceCount=").append(String.valueOf(mInstalledServices.size()));
+        pw.append("}");
+        pw.println();
+        pw.append("     Bound services:{");
+        final int serviceCount = mBoundServices.size();
+        for (int j = 0; j < serviceCount; j++) {
+            if (j > 0) {
+                pw.append(", ");
+                pw.println();
+                pw.append("                     ");
+            }
+            AccessibilityServiceConnection service = mBoundServices.get(j);
+            service.dump(fd, pw, args);
+        }
+        pw.println("}");
+        pw.append("     Enabled services:{");
+        Iterator<ComponentName> it = mEnabledServices.iterator();
+        if (it.hasNext()) {
+            ComponentName componentName = it.next();
+            pw.append(componentName.toShortString());
+            while (it.hasNext()) {
+                componentName = it.next();
+                pw.append(", ");
+                pw.append(componentName.toShortString());
+            }
+        }
+        pw.println("}");
+        pw.append("     Binding services:{");
+        it = mBindingServices.iterator();
+        if (it.hasNext()) {
+            ComponentName componentName = it.next();
+            pw.append(componentName.toShortString());
+            while (it.hasNext()) {
+                componentName = it.next();
+                pw.append(", ");
+                pw.append(componentName.toShortString());
+            }
+        }
+        pw.println("}");
+        pw.append("     Crashed services:{");
+        it = mCrashedServices.iterator();
+        if (it.hasNext()) {
+            ComponentName componentName = it.next();
+            pw.append(componentName.toShortString());
+            while (it.hasNext()) {
+                componentName = it.next();
+                pw.append(", ");
+                pw.append(componentName.toShortString());
+            }
+        }
+        pw.println("}]");
+    }
+
+    public boolean isAutoclickEnabledLocked() {
+        return mIsAutoclickEnabled;
+    }
+
+    public void setAutoclickEnabledLocked(boolean enabled) {
+        mIsAutoclickEnabled = enabled;
+    }
+
+    public boolean isDisplayMagnificationEnabledLocked() {
+        return mIsDisplayMagnificationEnabled;
+    }
+
+    public void setDisplayMagnificationEnabledLocked(boolean enabled) {
+        mIsDisplayMagnificationEnabled = enabled;
+    }
+
+    public boolean isFilterKeyEventsEnabledLocked() {
+        return mIsFilterKeyEventsEnabled;
+    }
+
+    public void setFilterKeyEventsEnabledLocked(boolean enabled) {
+        mIsFilterKeyEventsEnabled = enabled;
+    }
+
+    public int getInteractiveUiTimeoutLocked() {
+        return mInteractiveUiTimeout;
+    }
+
+    public void setInteractiveUiTimeoutLocked(int timeout) {
+        mInteractiveUiTimeout = timeout;
+    }
+
+    public int getLastSentClientStateLocked() {
+        return mLastSentClientState;
+    }
+
+    public void setLastSentClientStateLocked(int state) {
+        mLastSentClientState = state;
+    }
+
+    public boolean isNavBarMagnificationAssignedToAccessibilityButtonLocked() {
+        return mIsNavBarMagnificationAssignedToAccessibilityButton;
+    }
+
+    public void setNavBarMagnificationAssignedToAccessibilityButtonLocked(boolean assigned) {
+        mIsNavBarMagnificationAssignedToAccessibilityButton = assigned;
+    }
+
+    public boolean isNavBarMagnificationEnabledLocked() {
+        return mIsNavBarMagnificationEnabled;
+    }
+
+    public void setNavBarMagnificationEnabledLocked(boolean enabled) {
+        mIsNavBarMagnificationEnabled = enabled;
+    }
+
+    public int getNonInteractiveUiTimeoutLocked() {
+        return mNonInteractiveUiTimeout;
+    }
+
+    public void setNonInteractiveUiTimeoutLocked(int timeout) {
+        mNonInteractiveUiTimeout = timeout;
+    }
+
+    public boolean isPerformGesturesEnabledLocked() {
+        return mIsPerformGesturesEnabled;
+    }
+
+    public void setPerformGesturesEnabledLocked(boolean enabled) {
+        mIsPerformGesturesEnabled = enabled;
+    }
+
+    public ComponentName getServiceAssignedToAccessibilityButtonLocked() {
+        return mServiceAssignedToAccessibilityButton;
+    }
+
+    public void setServiceAssignedToAccessibilityButtonLocked(ComponentName componentName) {
+        mServiceAssignedToAccessibilityButton = componentName;
+    }
+
+    public ComponentName getServiceChangingSoftKeyboardModeLocked() {
+        return mServiceChangingSoftKeyboardMode;
+    }
+
+    public void setServiceChangingSoftKeyboardModeLocked(
+            ComponentName serviceChangingSoftKeyboardMode) {
+        mServiceChangingSoftKeyboardMode = serviceChangingSoftKeyboardMode;
+    }
+
+    public ComponentName getServiceToEnableWithShortcutLocked() {
+        return mServiceToEnableWithShortcut;
+    }
+
+    public void setServiceToEnableWithShortcutLocked(ComponentName componentName) {
+        mServiceToEnableWithShortcut = componentName;
+    }
+
+    public boolean isTextHighContrastEnabledLocked() {
+        return mIsTextHighContrastEnabled;
+    }
+
+    public void setTextHighContrastEnabledLocked(boolean enabled) {
+        mIsTextHighContrastEnabled = enabled;
+    }
+
+    public boolean isTouchExplorationEnabledLocked() {
+        return mIsTouchExplorationEnabled;
+    }
+
+    public void setTouchExplorationEnabledLocked(boolean enabled) {
+        mIsTouchExplorationEnabled = enabled;
+    }
+
+    public int getUserInteractiveUiTimeoutLocked() {
+        return mUserInteractiveUiTimeout;
+    }
+
+    public void setUserInteractiveUiTimeoutLocked(int timeout) {
+        mUserInteractiveUiTimeout = timeout;
+    }
+
+    public int getUserNonInteractiveUiTimeoutLocked() {
+        return mUserNonInteractiveUiTimeout;
+    }
+
+    public void setUserNonInteractiveUiTimeoutLocked(int timeout) {
+        mUserNonInteractiveUiTimeout = timeout;
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index b35300c..7d129ea 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -286,7 +286,7 @@
         window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
-        window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS);
+        window.addPrivateFlags(WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS);
         window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
         window.setGravity(Gravity.BOTTOM | Gravity.CENTER);
         window.setCloseOnTouchOutside(true);
diff --git a/services/backup/backuplib/java/com/android/server/backup/TransportManager.java b/services/backup/backuplib/java/com/android/server/backup/TransportManager.java
index de48f4b..30ce4cf 100644
--- a/services/backup/backuplib/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/backuplib/java/com/android/server/backup/TransportManager.java
@@ -93,8 +93,7 @@
         mTransportWhitelist = Preconditions.checkNotNull(whitelist);
         mCurrentTransportName = selectedTransport;
         mTransportStats = new TransportStats();
-        mTransportClientManager = TransportClientManager.createEncryptingClientManager(mUserId,
-                context, mTransportStats);
+        mTransportClientManager = new TransportClientManager(mUserId, context, mTransportStats);
     }
 
     @VisibleForTesting
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index e5e11ea..ac006df 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -239,7 +239,6 @@
     private final KeyValueBackupReporter mReporter;
     private final OnTaskFinishedListener mTaskFinishedListener;
     private final boolean mUserInitiated;
-    private final boolean mNonIncremental;
     private final int mCurrentOpToken;
     private final int mUserId;
     private final File mStateDirectory;
@@ -264,6 +263,7 @@
     // and at least one of the packages had data. Used to avoid updating current token for
     // empty backups.
     private boolean mHasDataToBackup;
+    private boolean mNonIncremental;
 
     /**
      * This {@link ConditionVariable} is used to signal that the cancel operation has been
@@ -412,6 +412,11 @@
         try {
             IBackupTransport transport = mTransportClient.connectOrThrow("KVBT.startTask()");
             String transportName = transport.name();
+            if (transportName.contains("EncryptedLocalTransport")) {
+                // Temporary code for EiTF POC. Only supports non-incremental backups.
+                mNonIncremental = true;
+            }
+
             mReporter.onTransportReady(transportName);
 
             // If we haven't stored PM metadata yet, we must initialize the transport.
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index c8dbb36..27824af 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -18,11 +18,13 @@
 
 import static android.Manifest.permission.MANAGE_CONTENT_CAPTURE;
 import static android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE;
+import static android.service.contentcapture.ContentCaptureService.setClientState;
 import static android.view.contentcapture.ContentCaptureHelper.toList;
 import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_FALSE;
 import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_OK;
 import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_SECURITY_EXCEPTION;
 import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_TRUE;
+import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED;
 
 import static com.android.internal.util.SyncResultReceiver.bundleFor;
 
@@ -520,6 +522,17 @@
         return true;
     }
 
+    @GuardedBy("mLock")
+    private boolean isDefaultServiceLocked(int userId) {
+        final String defaultServiceName = mServiceNameResolver.getDefaultServiceName(userId);
+        if (defaultServiceName == null) {
+            return false;
+        }
+
+        final String currentServiceName = mServiceNameResolver.getServiceName(userId);
+        return defaultServiceName.equals(currentServiceName);
+    }
+
     @Override // from AbstractMasterSystemService
     protected void dumpLocked(String prefix, PrintWriter pw) {
         super.dumpLocked(prefix, pw);
@@ -557,6 +570,10 @@
 
             synchronized (mLock) {
                 final ContentCapturePerUserService service = getServiceForUserLocked(userId);
+                if (!isDefaultServiceLocked(userId) && !isCalledByServiceLocked("startSession()")) {
+                    setClientState(result, STATE_DISABLED, /* binder= */ null);
+                    return;
+                }
                 service.startSessionLocked(activityToken, activityPresentationInfo, sessionId,
                         Binder.getCallingUid(), flags, result);
             }
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 1d666ad..dc24cff 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -59,6 +59,8 @@
     public static final int PACKAGE_CONFIGURATOR = 9;
     public static final int PACKAGE_INCIDENT_REPORT_APPROVER = 10;
     public static final int PACKAGE_APP_PREDICTOR = 11;
+    public static final int PACKAGE_TELEPHONY = 12;
+    public static final int PACKAGE_WIFI = 13;
     @IntDef(value = {
         PACKAGE_SYSTEM,
         PACKAGE_SETUP_WIZARD,
@@ -72,6 +74,8 @@
         PACKAGE_CONFIGURATOR,
         PACKAGE_INCIDENT_REPORT_APPROVER,
         PACKAGE_APP_PREDICTOR,
+        PACKAGE_TELEPHONY,
+        PACKAGE_WIFI,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface KnownPackage {}
@@ -546,10 +550,11 @@
      */
     public abstract boolean isResolveActivityComponent(@NonNull ComponentInfo component);
 
+
     /**
-     * Returns the package name for a known package.
+     * Returns a list of package names for a known package
      */
-    public abstract @Nullable String getKnownPackageName(
+    public abstract @NonNull String[] getKnownPackageNames(
             @KnownPackage int knownPackage, int userId);
 
     /**
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 9a97ddb..b41e95f 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -47,6 +47,7 @@
 import android.content.pm.PermissionInfo;
 import android.database.ContentObserver;
 import android.net.Uri;
+import android.os.BatteryManager;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -1564,6 +1565,7 @@
                     Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
 
             mClockReceiver = mInjector.getClockReceiver(this);
+            new ChargingReceiver();
             new InteractiveStateReceiver();
             new UninstallReceiver();
 
@@ -4148,7 +4150,7 @@
         public static final int LISTENER_TIMEOUT = 3;
         public static final int REPORT_ALARMS_ACTIVE = 4;
         public static final int APP_STANDBY_BUCKET_CHANGED = 5;
-        public static final int APP_STANDBY_PAROLE_CHANGED = 6;
+        public static final int CHARGING_STATUS_CHANGED = 6;
         public static final int REMOVE_FOR_STOPPED = 7;
         public static final int UNREGISTER_CANCEL_LISTENER = 8;
 
@@ -4206,7 +4208,7 @@
                     }
                     break;
 
-                case APP_STANDBY_PAROLE_CHANGED:
+                case CHARGING_STATUS_CHANGED:
                     synchronized (mLock) {
                         mAppStandbyParole = (Boolean) msg.obj;
                         if (reorderAlarmsBasedOnStandbyBuckets(null)) {
@@ -4247,6 +4249,37 @@
         }
     }
 
+    @VisibleForTesting
+    class ChargingReceiver extends BroadcastReceiver {
+        ChargingReceiver() {
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(BatteryManager.ACTION_CHARGING);
+            filter.addAction(BatteryManager.ACTION_DISCHARGING);
+            getContext().registerReceiver(this, filter);
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            final boolean charging;
+            if (BatteryManager.ACTION_CHARGING.equals(action)) {
+                if (DEBUG_STANDBY) {
+                    Slog.d(TAG, "Device is charging.");
+                }
+                charging = true;
+            } else {
+                if (DEBUG_STANDBY) {
+                    Slog.d(TAG, "Disconnected from power.");
+                }
+                charging = false;
+            }
+            mHandler.removeMessages(AlarmHandler.CHARGING_STATUS_CHANGED);
+            mHandler.obtainMessage(AlarmHandler.CHARGING_STATUS_CHANGED, charging)
+                    .sendToTarget();
+        }
+    }
+
+    @VisibleForTesting
     class ClockReceiver extends BroadcastReceiver {
         public ClockReceiver() {
             IntentFilter filter = new IntentFilter();
@@ -4429,7 +4462,7 @@
 
         @Override public void onUidCachedChanged(int uid, boolean cached) {
         }
-    };
+    }
 
     /**
      * Tracking of app assignments to standby buckets
@@ -4447,18 +4480,7 @@
             mHandler.obtainMessage(AlarmHandler.APP_STANDBY_BUCKET_CHANGED, userId, -1, packageName)
                     .sendToTarget();
         }
-
-        @Override
-        public void onParoleStateChanged(boolean isParoleOn) {
-            if (DEBUG_STANDBY) {
-                Slog.d(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
-            }
-            mHandler.removeMessages(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
-            mHandler.removeMessages(AlarmHandler.APP_STANDBY_PAROLE_CHANGED);
-            mHandler.obtainMessage(AlarmHandler.APP_STANDBY_PAROLE_CHANGED,
-                    Boolean.valueOf(isParoleOn)).sendToTarget();
-        }
-    };
+    }
 
     private final Listener mForceAppStandbyListener = new Listener() {
         @Override
diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java
index 2c67c50..da760b6 100644
--- a/services/core/java/com/android/server/AppStateTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -71,8 +71,7 @@
  * - Temporary power save whitelist
  * - Global "force all apps standby" mode enforced by battery saver.
  *
- * Test:
-  atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
+ * Test: atest com.android.server.AppStateTrackerTest
  */
 public class AppStateTracker {
     private static final String TAG = "AppStateTracker";
@@ -710,10 +709,6 @@
                 mHandler.notifyExemptChanged();
             }
         }
-
-        @Override
-        public void onParoleStateChanged(boolean isParoleOn) {
-        }
     }
 
     private Listener[] cloneListeners() {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index e0f60b4..0bb72cb 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1149,7 +1149,6 @@
     private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
         final NetworkCapabilities netCap = new NetworkCapabilities();
         netCap.addCapability(NET_CAPABILITY_INTERNET);
-        netCap.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
         netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
         netCap.setSingleUid(uid);
         return netCap;
@@ -1159,7 +1158,6 @@
             int transportType, NetworkRequest.Type type) {
         final NetworkCapabilities netCap = new NetworkCapabilities();
         netCap.addCapability(NET_CAPABILITY_INTERNET);
-        netCap.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
         if (transportType > -1) {
             netCap.addTransportType(transportType);
         }
diff --git a/services/core/java/com/android/server/GnssManagerService.java b/services/core/java/com/android/server/GnssManagerService.java
index b6e619e..44a8234 100644
--- a/services/core/java/com/android/server/GnssManagerService.java
+++ b/services/core/java/com/android/server/GnssManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.content.Context;
@@ -298,7 +299,8 @@
      * @param packageName name of requesting package
      * @return true if callback is successfully added, false otherwise
      */
-    public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
+    public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
+            @NonNull String listenerIdentity) {
         mContext.enforceCallingPermission(
                 android.Manifest.permission.LOCATION_HARDWARE,
                 "Location Hardware permission not granted to access hardware batching");
@@ -316,7 +318,8 @@
         }
 
         CallerIdentity callerIdentity =
-                new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
+                new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName,
+                        listenerIdentity);
         synchronized (mGnssBatchingLock) {
             mGnssBatchingCallback = callback;
             mGnssBatchingDeathCallback =
@@ -494,7 +497,7 @@
     private <TListener extends IInterface> boolean addGnssDataListenerLocked(
             TListener listener,
             String packageName,
-            String listenerName,
+            @NonNull String listenerIdentifier,
             RemoteListenerHelper<TListener> gnssDataProvider,
             ArrayMap<IBinder,
                     LinkedListener<TListener>> gnssDataListeners,
@@ -513,10 +516,11 @@
         }
 
         CallerIdentity callerIdentity =
-                new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
+                new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName,
+                        listenerIdentifier);
         LinkedListener<TListener> linkedListener =
                 new LocationManagerServiceUtils.LinkedListener<>(
-                        listener, listenerName, callerIdentity, binderDeathCallback);
+                        listener, listenerIdentifier, callerIdentity, binderDeathCallback);
         IBinder binder = listener.asBinder();
         if (!linkedListener.linkToListenerDeathNotificationLocked(binder)) {
             return false;
@@ -606,7 +610,7 @@
             return addGnssDataListenerLocked(
                     listener,
                     packageName,
-                    "GnssStatusListener",
+                    "Gnss status",
                     mGnssStatusProvider,
                     mGnssStatusListeners,
                     this::unregisterGnssStatusCallback);
@@ -632,12 +636,13 @@
      * @return true if listener is successfully added, false otherwise
      */
     public boolean addGnssMeasurementsListener(
-            IGnssMeasurementsListener listener, String packageName) {
+            IGnssMeasurementsListener listener, String packageName,
+            @NonNull String listenerIdentifier) {
         synchronized (mGnssMeasurementsListeners) {
             return addGnssDataListenerLocked(
                     listener,
                     packageName,
-                    "GnssMeasurementsListener",
+                    listenerIdentifier,
                     mGnssMeasurementsProvider,
                     mGnssMeasurementsListeners,
                     this::removeGnssMeasurementsListener);
@@ -689,12 +694,13 @@
      * @return true if listener is successfully added, false otherwise
      */
     public boolean addGnssNavigationMessageListener(
-            IGnssNavigationMessageListener listener, String packageName) {
+            IGnssNavigationMessageListener listener, String packageName,
+            @NonNull String listenerIdentifier) {
         synchronized (mGnssNavigationMessageListeners) {
             return addGnssDataListenerLocked(
                     listener,
                     packageName,
-                    "GnssNavigationMessageListener",
+                    listenerIdentifier,
                     mGnssNavigationMessageProvider,
                     mGnssNavigationMessageListeners,
                     this::removeGnssNavigationMessageListener);
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 09f62ff..1d22b82 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -62,8 +62,10 @@
 import android.location.LocationTime;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 import android.os.PowerManager;
 import android.os.PowerManager.ServiceType;
 import android.os.PowerManagerInternal;
@@ -119,6 +121,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
 
 /**
  * The service class that manages LocationProviders and issues location
@@ -145,11 +148,12 @@
     private static final String FUSED_LOCATION_SERVICE_ACTION =
             "com.android.location.service.FusedLocationProvider";
 
-    private static final long NANOS_PER_MILLI = 1000000L;
-
     // The maximum interval a location request can have and still be considered "high power".
     private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
 
+    // maximum age of a location before it is no longer considered "current"
+    private static final long MAX_CURRENT_LOCATION_AGE_MS = 10 * 1000;
+
     private static final int FOREGROUND_IMPORTANCE_CUTOFF
             = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
 
@@ -1223,8 +1227,10 @@
         PowerManager.WakeLock mWakeLock;
 
         private Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
-                String packageName, WorkSource workSource, boolean hideFromAppOps) {
-            super(new CallerIdentity(uid, pid, packageName), "LocationListener");
+                String packageName, WorkSource workSource, boolean hideFromAppOps,
+                @NonNull String listenerIdentifier) {
+            super(new CallerIdentity(uid, pid, packageName, listenerIdentifier),
+                    "LocationListener");
             mListener = listener;
             mPendingIntent = intent;
             if (listener != null) {
@@ -1532,9 +1538,12 @@
     }
 
     @Override
-    public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
+    public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
+            String listenerIdentifier) {
+        Preconditions.checkNotNull(listenerIdentifier);
+
         return mGnssManagerService == null ? false : mGnssManagerService.addGnssBatchingCallback(
-                callback, packageName);
+                callback, packageName, listenerIdentifier);
     }
 
     @Override
@@ -1696,11 +1705,12 @@
         }
     }
 
-    private boolean reportLocationAccessNoThrow(
-            int pid, int uid, String packageName, int allowedResolutionLevel) {
+    private boolean reportLocationAccessNoThrow(int pid, int uid, String packageName,
+            int allowedResolutionLevel, @Nullable String message) {
         int op = resolutionLevelToOp(allowedResolutionLevel);
         if (op >= 0) {
-            if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
+            if (mAppOps.noteOpNoThrow(op, uid, packageName, null, message)
+                    != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
         }
@@ -2133,12 +2143,13 @@
 
     @GuardedBy("mLock")
     private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
-            String packageName, WorkSource workSource, boolean hideFromAppOps) {
+            String packageName, WorkSource workSource, boolean hideFromAppOps,
+            @NonNull String listenerIdentifier) {
         IBinder binder = listener.asBinder();
         Receiver receiver = mReceivers.get(binder);
         if (receiver == null) {
             receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
-                    hideFromAppOps);
+                    hideFromAppOps, listenerIdentifier);
             if (!receiver.linkToListenerDeathNotificationLocked(
                     receiver.getListener().asBinder())) {
                 return null;
@@ -2150,11 +2161,11 @@
 
     @GuardedBy("mLock")
     private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
-            WorkSource workSource, boolean hideFromAppOps) {
+            WorkSource workSource, boolean hideFromAppOps, @NonNull String listenerIdentifier) {
         Receiver receiver = mReceivers.get(intent);
         if (receiver == null) {
             receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
-                    hideFromAppOps);
+                    hideFromAppOps, listenerIdentifier);
             mReceivers.put(intent, receiver);
         }
         return receiver;
@@ -2216,7 +2227,9 @@
 
     @Override
     public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
-            PendingIntent intent, String packageName) {
+            PendingIntent intent, String packageName, String listenerIdentifier) {
+        Preconditions.checkNotNull(listenerIdentifier);
+
         synchronized (mLock) {
             if (request == null) request = DEFAULT_LOCATION_REQUEST;
             checkPackageName(packageName);
@@ -2271,10 +2284,10 @@
                 Receiver receiver;
                 if (intent != null) {
                     receiver = getReceiverLocked(intent, pid, uid, packageName, workSource,
-                            hideFromAppOps);
+                            hideFromAppOps, listenerIdentifier);
                 } else {
                     receiver = getReceiverLocked(listener, pid, uid, packageName, workSource,
-                            hideFromAppOps);
+                            hideFromAppOps, listenerIdentifier);
                 }
                 requestLocationUpdatesLocked(sanitizedRequest, receiver, uid, packageName);
             } finally {
@@ -2343,9 +2356,9 @@
         synchronized (mLock) {
             Receiver receiver;
             if (intent != null) {
-                receiver = getReceiverLocked(intent, pid, uid, packageName, null, false);
+                receiver = getReceiverLocked(intent, pid, uid, packageName, null, false, "");
             } else {
-                receiver = getReceiverLocked(listener, pid, uid, packageName, null, false);
+                receiver = getReceiverLocked(listener, pid, uid, packageName, null, false, "");
             }
 
             long identity = Binder.clearCallingIdentity();
@@ -2441,8 +2454,8 @@
 
                 // Don't return stale location to apps with foreground-only location permission.
                 String op = resolutionLevelToOpStr(allowedResolutionLevel);
-                long locationAgeMs = SystemClock.elapsedRealtime()
-                        - location.getElapsedRealtimeNanos() / NANOS_PER_MILLI;
+                long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
+                        SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos());
                 if ((locationAgeMs > Settings.Global.getLong(
                         mContext.getContentResolver(),
                         Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
@@ -2464,8 +2477,8 @@
                 }
                 // Don't report location access if there is no last location to deliver.
                 if (lastLocation != null) {
-                    if (!reportLocationAccessNoThrow(
-                            pid, uid, packageName, allowedResolutionLevel)) {
+                    if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel,
+                            null)) {
                         if (D) {
                             Log.d(TAG, "not returning last loc for no op app: " + packageName);
                         }
@@ -2480,6 +2493,56 @@
     }
 
     @Override
+    public boolean getCurrentLocation(LocationRequest locationRequest,
+            ICancellationSignal remoteCancellationSignal, ILocationListener listener,
+            String packageName, String listenerIdentifier) {
+        // side effect of validating locationRequest and packageName
+        Location lastLocation = getLastLocation(locationRequest, packageName);
+        if (lastLocation != null) {
+            long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
+                    SystemClock.elapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos());
+
+            long identity = Binder.clearCallingIdentity();
+            try {
+                if (locationAgeMs < MAX_CURRENT_LOCATION_AGE_MS) {
+                    try {
+                        listener.onLocationChanged(lastLocation);
+                        return true;
+                    } catch (RemoteException e) {
+                        Log.w(TAG, e);
+                        return false;
+                    }
+                }
+
+                // packageName already validated by getLastLocation() call above
+                boolean foreground = LocationManagerServiceUtils.isImportanceForeground(
+                        mActivityManager.getPackageImportance(packageName));
+                if (!foreground) {
+                    long backgroundThrottleIntervalMs = Settings.Global.getLong(
+                            mContext.getContentResolver(),
+                            Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
+                            DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
+                    if (locationAgeMs < backgroundThrottleIntervalMs) {
+                        // not allowed to request new locations, so we can't return anything
+                        return false;
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        requestLocationUpdates(locationRequest, listener, null, packageName, listenerIdentifier);
+        CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
+                remoteCancellationSignal);
+        if (cancellationSignal != null) {
+            cancellationSignal.setOnCancelListener(
+                    () -> removeUpdates(listener, null, packageName));
+        }
+        return true;
+    }
+
+    @Override
     public LocationTime getGnssTimeMillis() {
         synchronized (mLock) {
             Location location = mLastLocation.get(LocationManager.GPS_PROVIDER);
@@ -2519,7 +2582,9 @@
 
     @Override
     public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
-            String packageName) {
+            String packageName, String listenerIdentifier) {
+        Preconditions.checkNotNull(listenerIdentifier);
+
         if (request == null) request = DEFAULT_LOCATION_REQUEST;
         int allowedResolutionLevel = getCallerAllowedResolutionLevel();
         checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
@@ -2564,9 +2629,8 @@
                         mActivityManager.getPackageImportance(packageName));
             }
 
-            mGeofenceManager.addFence(sanitizedRequest, geofence, intent,
-                    allowedResolutionLevel,
-                    uid, packageName);
+            mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
+                    uid, packageName, listenerIdentifier);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -2613,10 +2677,13 @@
     }
 
     @Override
-    public boolean addGnssMeasurementsListener(
-            IGnssMeasurementsListener listener, String packageName) {
+    public boolean addGnssMeasurementsListener(IGnssMeasurementsListener listener,
+            String packageName, String listenerIdentifier) {
+        Preconditions.checkNotNull(listenerIdentifier);
+
         return mGnssManagerService == null ? false
-                : mGnssManagerService.addGnssMeasurementsListener(listener, packageName);
+                : mGnssManagerService.addGnssMeasurementsListener(listener, packageName,
+                        listenerIdentifier);
     }
 
     @Override
@@ -2643,10 +2710,13 @@
     }
 
     @Override
-    public boolean addGnssNavigationMessageListener(
-            IGnssNavigationMessageListener listener, String packageName) {
+    public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
+            String packageName, String listenerIdentifier) {
+        Preconditions.checkNotNull(listenerIdentifier);
+
         return mGnssManagerService == null ? false
-                : mGnssManagerService.addGnssNavigationMessageListener(listener, packageName);
+                : mGnssManagerService.addGnssNavigationMessageListener(listener, packageName,
+                        listenerIdentifier);
     }
 
     @Override
@@ -2719,12 +2789,21 @@
                     return true;
                 }
             }
-
             return false;
         }
     }
 
     @Override
+    public List<String> getProviderPackages(String providerName) {
+        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG,
+                Manifest.permission.READ_DEVICE_CONFIG + " permission required");
+        synchronized (mLock) {
+            LocationProvider provider = getLocationProviderLocked(providerName);
+            return provider == null ? Collections.emptyList() : provider.getPackagesLocked();
+        }
+    }
+
+    @Override
     public void setExtraLocationControllerPackage(String packageName) {
         mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
                 Manifest.permission.LOCATION_HARDWARE + " permission required");
@@ -2811,9 +2890,9 @@
 
         // Check whether sufficient time has passed
         long minTime = record.mRealRequest.getFastestInterval();
-        long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
-                / NANOS_PER_MILLI;
-        if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
+        long deltaMs = TimeUnit.NANOSECONDS.toMillis(
+                loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos());
+        if (deltaMs < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
             return false;
         }
 
@@ -2868,9 +2947,9 @@
                 mLastLocationCoarseInterval.put(provider.getName(), lastLocationCoarseInterval);
             }
         }
-        long timeDiffNanos = location.getElapsedRealtimeNanos()
-                - lastLocationCoarseInterval.getElapsedRealtimeNanos();
-        if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
+        long timeDeltaMs = TimeUnit.NANOSECONDS.toMillis(location.getElapsedRealtimeNanos()
+                - lastLocationCoarseInterval.getElapsedRealtimeNanos());
+        if (timeDeltaMs > LocationFudger.FASTEST_INTERVAL_MS) {
             lastLocationCoarseInterval.set(location);
         }
         // Don't ever return a coarse location that is more recent than the allowed update
@@ -2943,7 +3022,8 @@
                             receiver.mCallerIdentity.mPid,
                             receiver.mCallerIdentity.mUid,
                             receiver.mCallerIdentity.mPackageName,
-                            receiver.mAllowedResolutionLevel)) {
+                            receiver.mAllowedResolutionLevel,
+                            "Location sent to " + receiver.mCallerIdentity.mListenerIdentifier)) {
                         if (D) {
                             Log.d(TAG, "skipping loc update for no op app: "
                                     + receiver.mCallerIdentity.mPackageName);
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index a502ff2..83ad4e7 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -104,6 +104,7 @@
             "android.hardware.audio@2.0::IDevicesFactory",
             "android.hardware.audio@4.0::IDevicesFactory",
             "android.hardware.audio@5.0::IDevicesFactory",
+            "android.hardware.audio@6.0::IDevicesFactory",
             "android.hardware.biometrics.face@1.0::IBiometricsFace",
             "android.hardware.bluetooth@1.0::IBluetoothHci",
             "android.hardware.camera.provider@2.4::ICameraProvider",
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 9209a21..eb77fea 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -569,7 +569,8 @@
                         r.lastActivity);
             }
             mAm.mAppOpsService.startOperation(AppOpsManager.getToken(mAm.mAppOpsService),
-                    AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, true);
+                    AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null,
+                    true);
         }
 
         final ServiceMap smap = getServiceMapLocked(r.userId);
@@ -1394,7 +1395,7 @@
                         mAm.mAppOpsService.startOperation(
                                 AppOpsManager.getToken(mAm.mAppOpsService),
                                 AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName,
-                                true);
+                                null, true);
                         StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
                                 r.appInfo.uid, r.shortInstanceName,
                                 StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER);
@@ -1427,7 +1428,8 @@
                     // we have cleared the flag so can now drop it.
                     mAm.mAppOpsService.finishOperation(
                             AppOpsManager.getToken(mAm.mAppOpsService),
-                            AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
+                            AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName,
+                            null);
                 }
             }
         } else {
@@ -1444,7 +1446,7 @@
                 }
                 mAm.mAppOpsService.finishOperation(
                         AppOpsManager.getToken(mAm.mAppOpsService),
-                        AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
+                        AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null);
                 StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
                         r.appInfo.uid, r.shortInstanceName,
                         StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
@@ -1819,7 +1821,7 @@
                                 || (callerApp.getCurProcState() <= ActivityManager.PROCESS_STATE_TOP
                                         && (flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0),
                         b.client);
-                mAm.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
+                mAm.updateOomAdjLocked(s.app, OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
             }
 
             if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
@@ -2701,7 +2703,7 @@
         bumpServiceExecutingLocked(r, execInFg, "create");
         mAm.updateLruProcessLocked(app, false, null);
         updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
-        mAm.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
+        mAm.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
 
         boolean created = false;
         try {
@@ -2981,7 +2983,7 @@
                         r.lastActivity);
             }
             mAm.mAppOpsService.finishOperation(AppOpsManager.getToken(mAm.mAppOpsService),
-                    AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
+                    AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null);
             mAm.mHandler.removeMessages(
                     ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
             if (r.app != null) {
@@ -3039,7 +3041,7 @@
             }
             mAm.mAppOpsService.finishOperation(
                     AppOpsManager.getToken(mAm.mAppOpsService),
-                    AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
+                    AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null);
             StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid,
                     r.shortInstanceName, StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
             mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 7fea5fc..9085d18 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -282,6 +282,19 @@
     // memory trimming.
     public int CUR_TRIM_CACHED_PROCESSES;
 
+    @SuppressWarnings("unused")
+    private static final int OOMADJ_UPDATE_POLICY_SLOW = 0;
+    private static final int OOMADJ_UPDATE_POLICY_QUICK = 1;
+    private static final int DEFAULT_OOMADJ_UPDATE_POLICY = OOMADJ_UPDATE_POLICY_QUICK;
+
+    private static final String KEY_OOMADJ_UPDATE_POLICY = "oomadj_update_policy";
+
+    // Indicate if the oom adjuster should take the quick path to update the oom adj scores,
+    // in which no futher actions will be performed if there are no significant adj/proc state
+    // changes for the specific process; otherwise, use the traditonal slow path which would
+    // keep updating all processes in the LRU list.
+    public boolean OOMADJ_UPDATE_QUICK = DEFAULT_OOMADJ_UPDATE_POLICY == OOMADJ_UPDATE_POLICY_QUICK;
+
     private static final long MIN_AUTOMATIC_HEAP_DUMP_PSS_THRESHOLD_BYTES = 100 * 1024; // 100 KB
 
     private final boolean mSystemServerAutomaticHeapDumpEnabled;
@@ -316,6 +329,9 @@
                             case KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED:
                                 updateBackgroundActivityStarts();
                                 break;
+                            case KEY_OOMADJ_UPDATE_POLICY:
+                                updateOomAdjUpdatePolicy();
+                                break;
                             default:
                                 break;
                         }
@@ -354,6 +370,7 @@
         updateMaxCachedProcesses();
         updateActivityStartsLoggingEnabled();
         updateBackgroundActivityStarts();
+        updateOomAdjUpdatePolicy();
     }
 
     public void setOverrideMaxCachedProcesses(int value) {
@@ -472,6 +489,14 @@
                 /*defaultValue*/ false);
     }
 
+    private void updateOomAdjUpdatePolicy() {
+        OOMADJ_UPDATE_QUICK = DeviceConfig.getInt(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_OOMADJ_UPDATE_POLICY,
+                /* defaultValue */ DEFAULT_OOMADJ_UPDATE_POLICY)
+                == OOMADJ_UPDATE_POLICY_QUICK;
+    }
+
     private void updateEnableAutomaticSystemServerHeapDumps() {
         if (!mSystemServerAutomaticHeapDumpEnabled) {
             Slog.wtf(TAG,
@@ -587,5 +612,6 @@
         pw.print("  CUR_MAX_EMPTY_PROCESSES="); pw.println(CUR_MAX_EMPTY_PROCESSES);
         pw.print("  CUR_TRIM_EMPTY_PROCESSES="); pw.println(CUR_TRIM_EMPTY_PROCESSES);
         pw.print("  CUR_TRIM_CACHED_PROCESSES="); pw.println(CUR_TRIM_CACHED_PROCESSES);
+        pw.print("  OOMADJ_UPDATE_QUICK="); pw.println(OOMADJ_UPDATE_QUICK);
     }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8c672a1..11cfe12 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -42,8 +42,6 @@
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
-import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
 import static android.os.FactoryTest.FACTORY_TEST_OFF;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
@@ -283,7 +281,6 @@
 import android.util.ArraySet;
 import android.util.DebugUtils;
 import android.util.EventLog;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.util.Pair;
 import android.util.PrintWriterPrinter;
@@ -381,7 +378,6 @@
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -424,7 +420,7 @@
     private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
     static final String TAG_LRU = TAG + POSTFIX_LRU;
     private static final String TAG_MU = TAG + POSTFIX_MU;
-    private static final String TAG_NETWORK = TAG + POSTFIX_NETWORK;
+    static final String TAG_NETWORK = TAG + POSTFIX_NETWORK;
     static final String TAG_OOM_ADJ = TAG + POSTFIX_OOM_ADJ;
     private static final String TAG_POWER = TAG + POSTFIX_POWER;
     static final String TAG_PROCESS_OBSERVERS = TAG + POSTFIX_PROCESS_OBSERVERS;
@@ -507,10 +503,6 @@
     static final int PERSISTENT_MASK =
             ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
 
-    // Intent sent when remote bugreport collection has been completed
-    private static final String INTENT_REMOTE_BUGREPORT_FINISHED =
-            "com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED";
-
     // If set, we will push process association information in to procstats.
     static final boolean TRACK_PROCSTATS_ASSOCIATIONS = true;
 
@@ -534,27 +526,10 @@
      */
     private static final int BINDER_PROXY_LOW_WATERMARK = 5500;
 
-    /**
-     * State indicating that there is no need for any blocking for network.
-     */
-    @VisibleForTesting
-    static final int NETWORK_STATE_NO_CHANGE = 0;
-
-    /**
-     * State indicating that the main thread needs to be informed about the network wait.
-     */
-    @VisibleForTesting
-    static final int NETWORK_STATE_BLOCK = 1;
-
-    /**
-     * State indicating that any threads waiting for network state to get updated can be unblocked.
-     */
-    @VisibleForTesting
-    static final int NETWORK_STATE_UNBLOCK = 2;
-
     // Max character limit for a notification title. If the notification title is larger than this
     // the notification will not be legible to the user.
     private static final int MAX_BUGREPORT_TITLE_SIZE = 50;
+    private static final int MAX_BUGREPORT_DESCRIPTION_SIZE = 150;
 
     private static final int NATIVE_DUMP_TIMEOUT_MS = 2000; // 2 seconds;
     private static final int JAVA_DUMP_MINIMUM_SIZE = 100; // 100 bytes.
@@ -900,7 +875,7 @@
 
         // The other observer methods are unused
         @Override
-        public void onIntentStarted(Intent intent) {
+        public void onIntentStarted(Intent intent, long timestampNs) {
         }
 
         @Override
@@ -912,7 +887,11 @@
         }
 
         @Override
-        public void onActivityLaunchFinished(byte[] finalActivity) {
+        public void onActivityLaunchFinished(byte[] finalActivity, long timestampNs) {
+        }
+
+        @Override
+        public void onReportFullyDrawn(byte[] finalActivity, long timestampNs) {
         }
     };
 
@@ -1360,7 +1339,7 @@
     String mTrackAllocationApp = null;
     String mNativeDebuggingApp = null;
 
-    private final Injector mInjector;
+    final Injector mInjector;
 
     static final class ProcessChangeItem {
         static final int CHANGE_ACTIVITIES = 1<<0;
@@ -3150,7 +3129,7 @@
 
     private boolean hasUsageStatsPermission(String callingPackage) {
         final int mode = mAppOpsService.noteOperation(AppOpsManager.OP_GET_USAGE_STATS,
-                Binder.getCallingUid(), callingPackage);
+                Binder.getCallingUid(), callingPackage, null);
         if (mode == AppOpsManager.MODE_DEFAULT) {
             return checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
                     == PackageManager.PERMISSION_GRANTED;
@@ -5171,7 +5150,7 @@
         }
 
         if (!didSomething) {
-            updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
+            updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
             checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
         }
 
@@ -5686,6 +5665,7 @@
 
     void importanceTokenDied(ImportanceToken token) {
         synchronized (ActivityManagerService.this) {
+            ProcessRecord pr = null;
             synchronized (mPidsSelfLocked) {
                 ImportanceToken cur
                     = mImportantProcesses.get(token.pid);
@@ -5693,14 +5673,14 @@
                     return;
                 }
                 mImportantProcesses.remove(token.pid);
-                ProcessRecord pr = mPidsSelfLocked.get(token.pid);
+                pr = mPidsSelfLocked.get(token.pid);
                 if (pr == null) {
                     return;
                 }
                 pr.forcingToImportant = null;
                 updateProcessForegroundLocked(pr, false, 0, false);
             }
-            updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
+            updateOomAdjLocked(pr, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
         }
     }
 
@@ -5711,8 +5691,9 @@
         synchronized(this) {
             boolean changed = false;
 
+            ProcessRecord pr = null;
             synchronized (mPidsSelfLocked) {
-                ProcessRecord pr = mPidsSelfLocked.get(pid);
+                pr = mPidsSelfLocked.get(pid);
                 if (pr == null && isForeground) {
                     Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
                     return;
@@ -5746,7 +5727,7 @@
             }
 
             if (changed) {
-                updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
+                updateOomAdjLocked(pr, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
             }
         }
     }
@@ -5852,8 +5833,9 @@
 
         @Override
         public int noteOp(String op, int uid, String packageName) {
+            // TODO moltmann: Allow to specify featureId
             return mActivityManagerService.mAppOpsService
-                    .noteOperation(AppOpsManager.strOpToOp(op), uid, packageName);
+                    .noteOperation(AppOpsManager.strOpToOp(op), uid, packageName, null);
         }
 
         @Override
@@ -6005,7 +5987,7 @@
         }
         // ...and legacy apps get an AppOp check
         int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND,
-                uid, packageName);
+                uid, packageName, null);
         if (DEBUG_BACKGROUND_CHECK) {
             Slog.i(TAG, "Legacy app " + uid + "/" + packageName + " bg appop " + appop);
         }
@@ -7890,7 +7872,7 @@
                     new HostingRecord("added application",
                             customProcess != null ? customProcess : info.processName));
             mProcessList.updateLruProcessLocked(app, false, null);
-            updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
+            updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
         }
 
         // This package really, really can not be stopped.
@@ -8247,24 +8229,18 @@
     }
 
     /**
-     * @deprecated This method is only used by a few internal components and it will soon start
-     * using bug report API (which will be restricted to a few, pre-defined apps).
-     * No new code should be calling it.
+     * Takes a bugreport using bug report API ({@code BugreportManager}) with no pre-set
+     * title and description
      */
-    // TODO(b/137825297): Remove deprecated annotation and rephrase comments for all
-    // requestBugreport functions below.
-    @Deprecated
     @Override
-    public void requestBugReport(int bugreportType) {
+    public void requestBugReport(@BugreportParams.BugreportMode int bugreportType) {
         requestBugReportWithDescription(null, null, bugreportType);
     }
 
     /**
-     * @deprecated This method is only used by a few internal components and it will soon start
-     * using bug report API (which will be restricted to a few, pre-defined apps).
-     * No new code should be calling it.
+     * Takes a bugreport using bug report API ({@code BugreportManager}) which gets
+     * triggered by sending a broadcast to Shell.
      */
-    @Deprecated
     @Override
     public void requestBugReportWithDescription(@Nullable String shareTitle,
             @Nullable String shareDescription, int bugreportType) {
@@ -8299,60 +8275,45 @@
 
         if (!TextUtils.isEmpty(shareTitle)) {
             if (shareTitle.length() > MAX_BUGREPORT_TITLE_SIZE) {
-                String errorStr = "shareTitle should be less than " +
-                        MAX_BUGREPORT_TITLE_SIZE + " characters";
+                String errorStr = "shareTitle should be less than "
+                        + MAX_BUGREPORT_TITLE_SIZE + " characters";
                 throw new IllegalArgumentException(errorStr);
             }
             if (!TextUtils.isEmpty(shareDescription)) {
-                int length = shareDescription.getBytes(StandardCharsets.UTF_8).length;
-                if (length > SystemProperties.PROP_VALUE_MAX) {
-                    String errorStr = "shareTitle should be less than " +
-                            SystemProperties.PROP_VALUE_MAX + " bytes";
+                if (shareDescription.length() > MAX_BUGREPORT_DESCRIPTION_SIZE) {
+                    String errorStr = "shareDescription should be less than "
+                            + MAX_BUGREPORT_DESCRIPTION_SIZE + " characters";
                     throw new IllegalArgumentException(errorStr);
-                } else {
-                    SystemProperties.set("dumpstate.options.description", shareDescription);
                 }
             }
-            SystemProperties.set("dumpstate.options.title", shareTitle);
             Slog.d(TAG, "Bugreport notification title " + shareTitle
                     + " description " + shareDescription);
         }
-        final boolean useApi = FeatureFlagUtils.isEnabled(mContext,
-                FeatureFlagUtils.USE_BUGREPORT_API);
-
-        if (useApi) {
-            // Create intent to trigger Bugreport API via Shell
-            Intent triggerShellBugreport = new Intent();
-            triggerShellBugreport.setAction(INTENT_BUGREPORT_REQUESTED);
-            triggerShellBugreport.setPackage(SHELL_APP_PACKAGE);
-            triggerShellBugreport.putExtra(EXTRA_BUGREPORT_TYPE, bugreportType);
-            triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-            triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
-            if (shareTitle != null) {
-                triggerShellBugreport.putExtra(EXTRA_TITLE, shareTitle);
-            }
-            if (shareDescription != null) {
-                triggerShellBugreport.putExtra(EXTRA_DESCRIPTION, shareDescription);
-            }
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                // Send broadcast to shell to trigger bugreport using Bugreport API
-                mContext.sendBroadcast(triggerShellBugreport);
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        } else {
-            SystemProperties.set("dumpstate.options", type);
-            SystemProperties.set("ctl.start", "bugreport");
+        // Create intent to trigger Bugreport API via Shell
+        Intent triggerShellBugreport = new Intent();
+        triggerShellBugreport.setAction(INTENT_BUGREPORT_REQUESTED);
+        triggerShellBugreport.setPackage(SHELL_APP_PACKAGE);
+        triggerShellBugreport.putExtra(EXTRA_BUGREPORT_TYPE, bugreportType);
+        triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+        if (shareTitle != null) {
+            triggerShellBugreport.putExtra(EXTRA_TITLE, shareTitle);
+        }
+        if (shareDescription != null) {
+            triggerShellBugreport.putExtra(EXTRA_DESCRIPTION, shareDescription);
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            // Send broadcast to shell to trigger bugreport using Bugreport API
+            mContext.sendBroadcast(triggerShellBugreport);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
     }
 
     /**
-     * @deprecated This method is only used by a few internal components and it will soon start
-     * using bug report API (which will be restricted to a few, pre-defined apps).
-     * No new code should be calling it.
+     * Takes a telephony bugreport with title and description
      */
-    @Deprecated
     @Override
     public void requestTelephonyBugReport(String shareTitle, String shareDescription) {
         requestBugReportWithDescription(shareTitle, shareDescription,
@@ -8360,11 +8321,8 @@
     }
 
     /**
-     * @deprecated This method is only used by a few internal components and it will soon start
-     * using bug report API (which will be restricted to a few, pre-defined apps).
-     * No new code should be calling it.
+     * Takes a minimal bugreport of Wifi-related state with pre-set title and description
      */
-    @Deprecated
     @Override
     public void requestWifiBugReport(String shareTitle, String shareDescription) {
         requestBugReportWithDescription(shareTitle, shareDescription,
@@ -8658,7 +8616,7 @@
         lp.format = v.getBackground().getOpacity();
         lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
-        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+        lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         ((WindowManager)mContext.getSystemService(
                 Context.WINDOW_SERVICE)).addView(v, lp);
     }
@@ -14966,12 +14924,10 @@
             HashSet<ComponentName> singleUserReceivers = null;
             boolean scannedFirstReceivers = false;
             for (int user : users) {
-                // Skip users that have Shell restrictions, with exception of always permitted
-                // Shell broadcasts
+                // Skip users that have Shell restrictions
                 if (callingUid == SHELL_UID
                         && mUserController.hasUserRestriction(
-                                UserManager.DISALLOW_DEBUGGING_FEATURES, user)
-                        && !isPermittedShellBroadcast(intent)) {
+                                UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
                     continue;
                 }
                 List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
@@ -15038,11 +14994,6 @@
         return receivers;
     }
 
-    private boolean isPermittedShellBroadcast(Intent intent) {
-        // remote bugreport should always be allowed to be taken
-        return INTENT_REMOTE_BUGREPORT_FINISHED.equals(intent.getAction());
-    }
-
     private void checkBroadcastFromSystem(Intent intent, ProcessRecord callerApp,
             String callerPackage, int callingUid, boolean isProtectedBroadcast, List receivers) {
         if ((intent.getFlags() & Intent.FLAG_RECEIVER_FROM_SHELL) != 0) {
@@ -17031,7 +16982,7 @@
             item.foregroundServiceTypes = fgServiceTypes;
 
             if (oomAdj) {
-                updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
+                updateOomAdjLocked(proc, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
             }
         }
     }
@@ -17286,6 +17237,16 @@
         mOomAdjuster.updateOomAdjLocked(oomAdjReason);
     }
 
+    /*
+     * Update OomAdj for a specific process and its reachable processes.
+     * @param app The process to update
+     * @param oomAdjReason
+     */
+    @GuardedBy("this")
+    final void updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
+        mOomAdjuster.updateOomAdjLocked(app, oomAdjReason);
+    }
+
     @Override
     public void makePackageIdle(String packageName, int userId) {
         if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
@@ -17352,115 +17313,6 @@
         }
     }
 
-    /**
-     * Checks if any uid is coming from background to foreground or vice versa and if so, increments
-     * the {@link UidRecord#curProcStateSeq} corresponding to that uid using global seq counter
-     * {@link ProcessList#mProcStateSeqCounter} and notifies the app if it needs to block.
-     */
-    @VisibleForTesting
-    @GuardedBy("this")
-    void incrementProcStateSeqAndNotifyAppsLocked() {
-        if (mWaitForNetworkTimeoutMs <= 0) {
-            return;
-        }
-        // Used for identifying which uids need to block for network.
-        ArrayList<Integer> blockingUids = null;
-        for (int i = mProcessList.mActiveUids.size() - 1; i >= 0; --i) {
-            final UidRecord uidRec = mProcessList.mActiveUids.valueAt(i);
-            // If the network is not restricted for uid, then nothing to do here.
-            if (!mInjector.isNetworkRestrictedForUid(uidRec.uid)) {
-                continue;
-            }
-            if (!UserHandle.isApp(uidRec.uid) || !uidRec.hasInternetPermission) {
-                continue;
-            }
-            // If process state is not changed, then there's nothing to do.
-            if (uidRec.setProcState == uidRec.getCurProcState()) {
-                continue;
-            }
-            final int blockState = getBlockStateForUid(uidRec);
-            // No need to inform the app when the blockState is NETWORK_STATE_NO_CHANGE as
-            // there's nothing the app needs to do in this scenario.
-            if (blockState == NETWORK_STATE_NO_CHANGE) {
-                continue;
-            }
-            synchronized (uidRec.networkStateLock) {
-                uidRec.curProcStateSeq = ++mProcessList.mProcStateSeqCounter; // TODO: use method
-                if (blockState == NETWORK_STATE_BLOCK) {
-                    if (blockingUids == null) {
-                        blockingUids = new ArrayList<>();
-                    }
-                    blockingUids.add(uidRec.uid);
-                } else {
-                    if (DEBUG_NETWORK) {
-                        Slog.d(TAG_NETWORK, "uid going to background, notifying all blocking"
-                                + " threads for uid: " + uidRec);
-                    }
-                    if (uidRec.waitingForNetwork) {
-                        uidRec.networkStateLock.notifyAll();
-                    }
-                }
-            }
-        }
-
-        // There are no uids that need to block, so nothing more to do.
-        if (blockingUids == null) {
-            return;
-        }
-
-        for (int i = mProcessList.mLruProcesses.size() - 1; i >= 0; --i) {
-            final ProcessRecord app = mProcessList.mLruProcesses.get(i);
-            if (!blockingUids.contains(app.uid)) {
-                continue;
-            }
-            if (!app.killedByAm && app.thread != null) {
-                final UidRecord uidRec = mProcessList.getUidRecordLocked(app.uid);
-                try {
-                    if (DEBUG_NETWORK) {
-                        Slog.d(TAG_NETWORK, "Informing app thread that it needs to block: "
-                                + uidRec);
-                    }
-                    if (uidRec != null) {
-                        app.thread.setNetworkBlockSeq(uidRec.curProcStateSeq);
-                    }
-                } catch (RemoteException ignored) {
-                }
-            }
-        }
-    }
-
-    /**
-     * Checks if the uid is coming from background to foreground or vice versa and returns
-     * appropriate block state based on this.
-     *
-     * @return blockState based on whether the uid is coming from background to foreground or
-     *         vice versa. If bg->fg or fg->bg, then {@link #NETWORK_STATE_BLOCK} or
-     *         {@link #NETWORK_STATE_UNBLOCK} respectively, otherwise
-     *         {@link #NETWORK_STATE_NO_CHANGE}.
-     */
-    @VisibleForTesting
-    int getBlockStateForUid(UidRecord uidRec) {
-        // Denotes whether uid's process state is currently allowed network access.
-        final boolean isAllowed =
-                isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.getCurProcState())
-                || isProcStateAllowedWhileOnRestrictBackground(uidRec.getCurProcState());
-        // Denotes whether uid's process state was previously allowed network access.
-        final boolean wasAllowed = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.setProcState)
-                || isProcStateAllowedWhileOnRestrictBackground(uidRec.setProcState);
-
-        // When the uid is coming to foreground, AMS should inform the app thread that it should
-        // block for the network rules to get updated before launching an activity.
-        if (!wasAllowed && isAllowed) {
-            return NETWORK_STATE_BLOCK;
-        }
-        // When the uid is going to background, AMS should inform the app thread that if an
-        // activity launch is blocked for the network rules to get updated, it should be unblocked.
-        if (wasAllowed && !isAllowed) {
-            return NETWORK_STATE_UNBLOCK;
-        }
-        return NETWORK_STATE_NO_CHANGE;
-    }
-
     final void runInBackgroundDisabled(int uid) {
         synchronized (this) {
             UidRecord uidRec = mProcessList.getUidRecordLocked(uid);
@@ -19310,18 +19162,19 @@
         }
 
         @Override
-        public int noteOperation(int code, int uid, String packageName,
-                TriFunction<Integer, Integer, String, Integer> superImpl) {
+        public int noteOperation(int code, int uid, @Nullable String packageName,
+                @Nullable String featureId,
+                @NonNull QuadFunction<Integer, Integer, String, String, Integer> superImpl) {
             if (uid == mTargetUid && isTargetOp(code)) {
                 final long identity = Binder.clearCallingIdentity();
                 try {
                     return mAppOpsService.noteProxyOperation(code, Process.SHELL_UID,
-                            "com.android.shell", uid, packageName);
+                            "com.android.shell", null, uid, packageName, featureId);
                 } finally {
                     Binder.restoreCallingIdentity(identity);
                 }
             }
-            return superImpl.apply(code, uid, packageName);
+            return superImpl.apply(code, uid, packageName, featureId);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index a80a5b5..852c9b65 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -92,7 +92,7 @@
         WindowManager.LayoutParams attrs = getWindow().getAttributes();
         attrs.setTitle("Application Error: " + mProc.info.processName);
         attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR
-                | WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+                | WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         getWindow().setAttributes(attrs);
         if (mProc.isPersistent()) {
             getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index cb76e2f..65d7e01 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -94,7 +94,7 @@
         WindowManager.LayoutParams attrs = getWindow().getAttributes();
         attrs.setTitle("Application Not Responding: " + mProc.info.processName);
         attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR |
-                WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+                WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         getWindow().setAttributes(attrs);
     }
 
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 59c2326..1d03b36 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -309,7 +309,7 @@
         app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
         mService.mProcessList.updateLruProcessLocked(app, false, null);
         if (!skipOomAdj) {
-            mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+            mService.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
         }
 
         // Tell the application to launch this receiver.
@@ -647,9 +647,10 @@
                 skip = true;
             } else {
                 final int opCode = AppOpsManager.permissionToOpCode(filter.requiredPermission);
+                // TODO moltmann: Set featureId from caller
                 if (opCode != AppOpsManager.OP_NONE
                         && mService.mAppOpsService.noteOperation(opCode, r.callingUid,
-                                r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
+                                r.callerPackage, null) != AppOpsManager.MODE_ALLOWED) {
                     Slog.w(TAG, "Appop Denial: broadcasting "
                             + r.intent.toString()
                             + " from " + r.callerPackage + " (pid="
@@ -679,9 +680,10 @@
                     break;
                 }
                 int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
+                // TODO moltmann: Set componentId from caller
                 if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
                         && mService.mAppOpsService.noteOperation(appOp,
-                        filter.receiverList.uid, filter.packageName)
+                        filter.receiverList.uid, filter.packageName, null)
                         != AppOpsManager.MODE_ALLOWED) {
                     Slog.w(TAG, "Appop Denial: receiving "
                             + r.intent.toString()
@@ -711,9 +713,10 @@
                 skip = true;
             }
         }
+        // TODO moltmann: Set componentId from caller
         if (!skip && r.appOp != AppOpsManager.OP_NONE
                 && mService.mAppOpsService.noteOperation(r.appOp,
-                filter.receiverList.uid, filter.packageName)
+                filter.receiverList.uid, filter.packageName, null)
                 != AppOpsManager.MODE_ALLOWED) {
             Slog.w(TAG, "Appop Denial: receiving "
                     + r.intent.toString()
@@ -1367,9 +1370,10 @@
             skip = true;
         } else if (!skip && info.activityInfo.permission != null) {
             final int opCode = AppOpsManager.permissionToOpCode(info.activityInfo.permission);
+            // TODO moltmann: Set componentId from caller
             if (opCode != AppOpsManager.OP_NONE
                     && mService.mAppOpsService.noteOperation(opCode, r.callingUid,
-                            r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
+                            r.callerPackage, null) != AppOpsManager.MODE_ALLOWED) {
                 Slog.w(TAG, "Appop Denial: broadcasting "
                         + r.intent.toString()
                         + " from " + r.callerPackage + " (pid="
@@ -1405,9 +1409,10 @@
                     break;
                 }
                 int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
+                // TODO moltmann: Set componentId from caller
                 if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
                         && mService.mAppOpsService.noteOperation(appOp,
-                        info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
+                        info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, null)
                         != AppOpsManager.MODE_ALLOWED) {
                     Slog.w(TAG, "Appop Denial: receiving "
                             + r.intent + " to "
@@ -1421,9 +1426,10 @@
                 }
             }
         }
+        // TODO moltmann: Set componentId from caller
         if (!skip && r.appOp != AppOpsManager.OP_NONE
                 && mService.mAppOpsService.noteOperation(r.appOp,
-                info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
+                info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, null)
                 != AppOpsManager.MODE_ALLOWED) {
             Slog.w(TAG, "Appop Denial: receiving "
                     + r.intent + " to "
diff --git a/services/core/java/com/android/server/am/OomAdjProfiler.java b/services/core/java/com/android/server/am/OomAdjProfiler.java
index 7e381840..0869114 100644
--- a/services/core/java/com/android/server/am/OomAdjProfiler.java
+++ b/services/core/java/com/android/server/am/OomAdjProfiler.java
@@ -45,7 +45,7 @@
     private boolean mLastScheduledScreenOff;
 
     @GuardedBy("this")
-    private long mOomAdjStartTimeMs;
+    private long mOomAdjStartTimeUs;
     @GuardedBy("this")
     private boolean mOomAdjStarted;
 
@@ -65,6 +65,11 @@
     @GuardedBy("this")
     final RingBuffer<CpuTimes> mSystemServerCpuTimesHist = new RingBuffer<>(CpuTimes.class, 10);
 
+    @GuardedBy("this")
+    private long mTotalOomAdjRunTimeUs;
+    @GuardedBy("this")
+    private int mTotalOomAdjCalls;
+
     void batteryPowerChanged(boolean onBattery) {
         synchronized (this) {
             scheduleSystemServerCpuTimeUpdate();
@@ -81,7 +86,7 @@
 
     void oomAdjStarted() {
         synchronized (this) {
-            mOomAdjStartTimeMs = SystemClock.currentThreadTimeMillis();
+            mOomAdjStartTimeUs = SystemClock.currentThreadTimeMicro();
             mOomAdjStarted = true;
         }
     }
@@ -91,7 +96,10 @@
             if (!mOomAdjStarted) {
                 return;
             }
-            mOomAdjRunTime.addCpuTimeMs(SystemClock.currentThreadTimeMillis() - mOomAdjStartTimeMs);
+            long elapsedUs = SystemClock.currentThreadTimeMicro() - mOomAdjStartTimeUs;
+            mOomAdjRunTime.addCpuTimeUs(elapsedUs);
+            mTotalOomAdjRunTimeUs += elapsedUs;
+            mTotalOomAdjCalls++;
         }
     }
 
@@ -169,32 +177,50 @@
                 pw.print("oom_adj=");
                 pw.println(oomAdjRunTimes[i]);
             }
+            if (mTotalOomAdjCalls != 0) {
+                pw.println("System server total oomAdj runtimes (us) since boot:");
+                pw.print("  cpu time spent=");
+                pw.print(mTotalOomAdjRunTimeUs);
+                pw.print("  number of calls=");
+                pw.print(mTotalOomAdjCalls);
+                pw.print("  average=");
+                pw.println(mTotalOomAdjRunTimeUs / mTotalOomAdjCalls);
+            }
         }
     }
 
     private class CpuTimes {
-        private long mOnBatteryTimeMs;
-        private long mOnBatteryScreenOffTimeMs;
+        private long mOnBatteryTimeUs;
+        private long mOnBatteryScreenOffTimeUs;
 
         public void addCpuTimeMs(long cpuTimeMs) {
-            addCpuTimeMs(cpuTimeMs, mOnBattery, mScreenOff);
+            addCpuTimeUs(cpuTimeMs * 1000, mOnBattery, mScreenOff);
         }
 
         public void addCpuTimeMs(long cpuTimeMs, boolean onBattery, boolean screenOff) {
+            addCpuTimeUs(cpuTimeMs * 1000, onBattery, screenOff);
+        }
+
+        public void addCpuTimeUs(long cpuTimeUs) {
+            addCpuTimeUs(cpuTimeUs, mOnBattery, mScreenOff);
+        }
+
+        public void addCpuTimeUs(long cpuTimeUs, boolean onBattery, boolean screenOff) {
             if (onBattery) {
-                mOnBatteryTimeMs += cpuTimeMs;
+                mOnBatteryTimeUs += cpuTimeUs;
                 if (screenOff) {
-                    mOnBatteryScreenOffTimeMs += cpuTimeMs;
+                    mOnBatteryScreenOffTimeUs += cpuTimeUs;
                 }
             }
         }
 
         public boolean isEmpty() {
-            return mOnBatteryTimeMs == 0 && mOnBatteryScreenOffTimeMs == 0;
+            return mOnBatteryTimeUs == 0 && mOnBatteryScreenOffTimeUs == 0;
         }
 
         public String toString() {
-            return "[" + mOnBatteryTimeMs + "," + mOnBatteryScreenOffTimeMs + "]";
+            return "[" + (mOnBatteryTimeUs / 1000) + ","
+                    + (mOnBatteryScreenOffTimeUs / 1000) + "]";
         }
     }
 }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index bb214bd..6bba7d5 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -19,7 +19,9 @@
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
+import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
 import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT;
 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION;
 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
@@ -62,6 +64,7 @@
 import android.app.ActivityManager;
 import android.app.usage.UsageEvents;
 import android.content.Context;
+import android.content.pm.ServiceInfo;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.IBinder;
@@ -85,6 +88,7 @@
 import com.android.server.wm.WindowProcessController;
 
 import java.io.PrintWriter;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
 
@@ -162,6 +166,12 @@
     private final ActivityManagerService mService;
     private final ProcessList mProcessList;
 
+    private final int mNumSlots;
+    private ArrayList<ProcessRecord> mTmpProcessList = new ArrayList<ProcessRecord>();
+    private ArrayList<UidRecord> mTmpBecameIdle = new ArrayList<UidRecord>();
+    private ActiveUids mTmpUidRecords;
+    private ArrayDeque<ProcessRecord> mTmpQueue;
+
     OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) {
         this(service, processList, activeUids, createAdjusterThread());
     }
@@ -204,6 +214,10 @@
             }
             return true;
         });
+        mTmpUidRecords = new ActiveUids(service, false);
+        mTmpQueue = new ArrayDeque<ProcessRecord>(mConstants.CUR_MAX_CACHED_PROCESSES << 1);
+        mNumSlots = ((ProcessList.CACHED_APP_MAX_ADJ - ProcessList.CACHED_APP_MIN_ADJ + 1) >> 1)
+                / ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
     }
 
     void initSettings() {
@@ -221,6 +235,9 @@
     @GuardedBy("mService")
     boolean updateOomAdjLocked(ProcessRecord app, boolean oomAdjAll,
             String oomAdjReason) {
+        if (oomAdjAll && mConstants.OOMADJ_UPDATE_QUICK) {
+            return updateOomAdjLocked(app, oomAdjReason);
+        }
         final ProcessRecord TOP_APP = mService.getTopAppLocked();
         final boolean wasCached = app.cached;
 
@@ -250,26 +267,188 @@
             return false;
         }
 
-        computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now, false);
+        app.resetCachedInfo();
+        UidRecord uidRec = app.uidRecord;
+        if (uidRec != null) {
+            if (DEBUG_UID_OBSERVERS) {
+                Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
+            }
+            uidRec.reset();
+        }
 
-        return applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
+        computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now, false, true);
+
+        boolean success = applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
+
+        if (uidRec != null) {
+            updateAppUidRecLocked(app);
+            // If this proc state is changed, need to update its uid record here
+            if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
+                    && (uidRec.setProcState != uidRec.getCurProcState()
+                    || uidRec.setWhitelist != uidRec.curWhitelist)) {
+                ActiveUids uids = mTmpUidRecords;
+                uids.clear();
+                uids.put(uidRec.uid, uidRec);
+                updateUidsLocked(uids, now);
+                mProcessList.incrementProcStateSeqAndNotifyAppsLocked(uids);
+            }
+        }
+
+        return success;
     }
 
+    /**
+     * Update OomAdj for all processes in LRU list
+     */
     @GuardedBy("mService")
     void updateOomAdjLocked(String oomAdjReason) {
+        final ProcessRecord topApp = mService.getTopAppLocked();
+        updateOomAdjLockedInner(oomAdjReason, topApp , null, null, true);
+    }
+
+    /**
+     * Update OomAdj for specific process and its reachable processes (with direction/indirect
+     * bindings from this process); Note its clients' proc state won't be re-evaluated if this proc
+     * is hosting any service/content provider.
+     *
+     * @param app The process to update, or null to update all processes
+     * @param oomAdjReason
+     */
+    @GuardedBy("mService")
+    boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
+        if (app == null || !mConstants.OOMADJ_UPDATE_QUICK) {
+            updateOomAdjLocked(oomAdjReason);
+            return true;
+        }
+
+        final ProcessRecord topApp = mService.getTopAppLocked();
+
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
         mService.mOomAdjProfiler.oomAdjStarted();
-        final ProcessRecord TOP_APP = mService.getTopAppLocked();
+        mAdjSeq++;
+
+        // Firstly, try to see if the importance of itself gets changed
+        final boolean wasCached = app.cached;
+        final int oldAdj = app.getCurRawAdj();
+        final int cachedAdj = oldAdj >= ProcessList.CACHED_APP_MIN_ADJ
+                ? oldAdj : ProcessList.UNKNOWN_ADJ;
+        final boolean wasBackground = ActivityManager.isProcStateBackground(app.setProcState);
+        app.containsCycle = false;
+        app.procStateChanged = false;
+        app.resetCachedInfo();
+        boolean success = updateOomAdjLocked(app, cachedAdj, topApp, false,
+                SystemClock.uptimeMillis());
+        if (!success || (wasCached == app.cached && oldAdj != ProcessList.INVALID_ADJ
+                && wasBackground == ActivityManager.isProcStateBackground(app.setProcState))) {
+            // Okay, it's unchanged, it won't impact any service it binds to, we're done here.
+            if (DEBUG_OOM_ADJ) {
+                Slog.i(TAG_OOM_ADJ, "No oomadj changes for " + app);
+            }
+            mService.mOomAdjProfiler.oomAdjEnded();
+            return success;
+        }
+
+        // Next to find out all its reachable processes
+        ArrayList<ProcessRecord> processes = mTmpProcessList;
+        ActiveUids uids = mTmpUidRecords;
+        ArrayDeque<ProcessRecord> queue = mTmpQueue;
+
+        processes.clear();
+        uids.clear();
+        queue.clear();
+
+        // borrow the "containsCycle" flag to mark it being scanned
+        app.containsCycle = true;
+        for (ProcessRecord pr = app; pr != null; pr = queue.poll()) {
+            if (pr != app) {
+                processes.add(pr);
+            }
+            if (pr.uidRecord != null) {
+                uids.put(pr.uidRecord.uid, pr.uidRecord);
+            }
+            for (int i = pr.connections.size() - 1; i >= 0; i--) {
+                ConnectionRecord cr = pr.connections.valueAt(i);
+                ProcessRecord service = (cr.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
+                        ? cr.binding.service.isolatedProc : cr.binding.service.app;
+                if (service == null || service.containsCycle) {
+                    continue;
+                }
+                if ((cr.flags & (Context.BIND_WAIVE_PRIORITY
+                        | Context.BIND_TREAT_LIKE_ACTIVITY
+                        | Context.BIND_ADJUST_WITH_ACTIVITY))
+                        == Context.BIND_WAIVE_PRIORITY) {
+                    continue;
+                }
+                queue.offer(service);
+                service.containsCycle = true;
+            }
+            for (int i = pr.conProviders.size() - 1; i >= 0; i--) {
+                ContentProviderConnection cpc = pr.conProviders.get(i);
+                ProcessRecord provider = cpc.provider.proc;
+                if (provider == null || provider.containsCycle) {
+                    continue;
+                }
+                queue.offer(provider);
+                provider.containsCycle = true;
+            }
+        }
+
+        // Reset the flag
+        app.containsCycle = false;
+        int size = processes.size();
+        if (size > 0) {
+            // Reverse the process list, since the updateOomAdjLockedInner scans from the end of it.
+            for (int l = 0, r = size - 1; l < r; l++, r--) {
+                ProcessRecord t = processes.get(l);
+                processes.set(l, processes.get(r));
+                processes.set(r, t);
+            }
+            mAdjSeq--;
+            // Update these reachable processes
+            updateOomAdjLockedInner(oomAdjReason, topApp, processes, uids, false);
+        }
+        mService.mOomAdjProfiler.oomAdjEnded();
+        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+        return true;
+    }
+
+    /**
+     * Update OomAdj for all processes within the given list (could be partial), or the whole LRU
+     * list if the given list is null; when it's partial update, each process's client proc won't
+     * get evaluated recursively here.
+     */
+    @GuardedBy("mService")
+    private void updateOomAdjLockedInner(String oomAdjReason, final ProcessRecord topApp,
+            ArrayList<ProcessRecord> processes, ActiveUids uids, boolean startProfiling) {
+        if (startProfiling) {
+            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
+            mService.mOomAdjProfiler.oomAdjStarted();
+        }
         final long now = SystemClock.uptimeMillis();
         final long nowElapsed = SystemClock.elapsedRealtime();
         final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
-        final int N = mProcessList.getLruSizeLocked();
+        final boolean fullUpdate = processes == null;
+        ActiveUids activeUids = uids;
+        ArrayList<ProcessRecord> activeProcesses = fullUpdate ? mProcessList.mLruProcesses
+                : processes;
+        final int numProc = activeProcesses.size();
+
+        if (activeUids == null) {
+            final int numUids = mActiveUids.size();
+            activeUids = mTmpUidRecords;
+            activeUids.clear();
+            for (int i = 0; i < numUids; i++) {
+                UidRecord r = mActiveUids.valueAt(i);
+                activeUids.put(r.uid, r);
+            }
+        }
 
         // Reset state in all uid records.
-        for (int  i = mActiveUids.size() - 1; i >= 0; i--) {
-            final UidRecord uidRec = mActiveUids.valueAt(i);
-            if (false && DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
-                    "Starting update of " + uidRec);
+        for (int  i = activeUids.size() - 1; i >= 0; i--) {
+            final UidRecord uidRec = activeUids.valueAt(i);
+            if (DEBUG_UID_OBSERVERS) {
+                Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
+            }
             uidRec.reset();
         }
 
@@ -278,48 +457,112 @@
         }
 
         mAdjSeq++;
-        mNewNumServiceProcs = 0;
-        mNewNumAServiceProcs = 0;
-
-        final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
-        final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
-                - emptyProcessLimit;
-
-        // Let's determine how many processes we have running vs.
-        // how many slots we have for background processes; we may want
-        // to put multiple processes in a slot of there are enough of
-        // them.
-        final int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
-                - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2
-                / ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
-        int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;
-        if (numEmptyProcs > cachedProcessLimit) {
-            // If there are more empty processes than our limit on cached
-            // processes, then use the cached process limit for the factor.
-            // This ensures that the really old empty processes get pushed
-            // down to the bottom, so if we are running low on memory we will
-            // have a better chance at keeping around more cached processes
-            // instead of a gazillion empty processes.
-            numEmptyProcs = cachedProcessLimit;
+        if (fullUpdate) {
+            mNewNumServiceProcs = 0;
+            mNewNumAServiceProcs = 0;
         }
-        int emptyFactor = (numEmptyProcs + numSlots - 1) / numSlots;
-        if (emptyFactor < 1) emptyFactor = 1;
-        int cachedFactor = (mNumCachedHiddenProcs > 0 ? (mNumCachedHiddenProcs + numSlots - 1) : 1)
-                / numSlots;
-        if (cachedFactor < 1) cachedFactor = 1;
-        int stepCached = -1;
-        int stepEmpty = -1;
-        int numCached = 0;
-        int numCachedExtraGroup = 0;
-        int numEmpty = 0;
-        int numTrimming = 0;
-        int lastCachedGroup = 0;
-        int lastCachedGroupImportance = 0;
-        int lastCachedGroupUid = 0;
+
+        boolean retryCycles = false;
+
+        // need to reset cycle state before calling computeOomAdjLocked because of service conns
+        for (int i = numProc - 1; i >= 0; i--) {
+            ProcessRecord app = activeProcesses.get(i);
+            app.containsCycle = false;
+            app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
+            app.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
+            app.resetCachedInfo();
+        }
+        for (int i = numProc - 1; i >= 0; i--) {
+            ProcessRecord app = activeProcesses.get(i);
+            if (!app.killedByAm && app.thread != null) {
+                app.procStateChanged = false;
+                computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, topApp, fullUpdate, now, false,
+                        fullUpdate); // It won't enter cycle if not computing clients.
+                // if any app encountered a cycle, we need to perform an additional loop later
+                retryCycles |= app.containsCycle;
+                // Keep the completedAdjSeq to up to date.
+                app.completedAdjSeq = mAdjSeq;
+            }
+        }
+
+        assignCachedAdjIfNecessary();
+
+        if (fullUpdate) { // There won't be cycles if we didn't compute clients above.
+            // Cycle strategy:
+            // - Retry computing any process that has encountered a cycle.
+            // - Continue retrying until no process was promoted.
+            // - Iterate from least important to most important.
+            int cycleCount = 0;
+            while (retryCycles && cycleCount < 10) {
+                cycleCount++;
+                retryCycles = false;
+
+                for (int i = 0; i < numProc; i++) {
+                    ProcessRecord app = activeProcesses.get(i);
+                    if (!app.killedByAm && app.thread != null && app.containsCycle) {
+                        app.adjSeq--;
+                        app.completedAdjSeq--;
+                    }
+                }
+
+                for (int i = 0; i < numProc; i++) {
+                    ProcessRecord app = activeProcesses.get(i);
+                    if (!app.killedByAm && app.thread != null && app.containsCycle) {
+                        if (computeOomAdjLocked(app, app.getCurRawAdj(), topApp, true, now,
+                                true, true)) {
+                            retryCycles = true;
+                        }
+                    }
+                }
+            }
+        }
 
         mNumNonCachedProcs = 0;
         mNumCachedHiddenProcs = 0;
 
+        boolean allChanged = updateAndTrimProcessLocked(now, nowElapsed, oldTime, activeUids);
+        mNumServiceProcs = mNewNumServiceProcs;
+
+        if (mService.mAlwaysFinishActivities) {
+            // Need to do this on its own message because the stack may not
+            // be in a consistent state at this point.
+            mService.mAtmInternal.scheduleDestroyAllActivities("always-finish");
+        }
+
+        if (allChanged) {
+            mService.requestPssAllProcsLocked(now, false,
+                    mService.mProcessStats.isMemFactorLowered());
+        }
+
+        updateUidsLocked(activeUids, nowElapsed);
+
+        if (mService.mProcessStats.shouldWriteNowLocked(now)) {
+            mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService,
+                    mService.mProcessStats));
+        }
+
+        // Run this after making sure all procstates are updated.
+        mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now);
+
+        if (DEBUG_OOM_ADJ) {
+            final long duration = SystemClock.uptimeMillis() - now;
+            if (false) {
+                Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms",
+                        new RuntimeException("here").fillInStackTrace());
+            } else {
+                Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms");
+            }
+        }
+        if (startProfiling) {
+            mService.mOomAdjProfiler.oomAdjEnded();
+            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+        }
+    }
+
+    private void assignCachedAdjIfNecessary() {
+        ArrayList<ProcessRecord> lruList = mProcessList.mLruProcesses;
+        final int numLru = lruList.size();
+
         // First update the OOM adjustment for each of the
         // application processes based on their current state.
         int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
@@ -328,136 +571,143 @@
         int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
         int nextEmptyAdj = curEmptyAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2);
 
-        boolean retryCycles = false;
-
-        // need to reset cycle state before calling computeOomAdjLocked because of service conns
-        for (int i = N - 1; i >= 0; i--) {
-            ProcessRecord app = mProcessList.mLruProcesses.get(i);
-            app.containsCycle = false;
-            app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
-            app.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
+        final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
+        final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
+                - emptyProcessLimit;
+        // Let's determine how many processes we have running vs.
+        // how many slots we have for background processes; we may want
+        // to put multiple processes in a slot of there are enough of
+        // them.
+        int numEmptyProcs = numLru - mNumNonCachedProcs - mNumCachedHiddenProcs;
+        if (numEmptyProcs > cachedProcessLimit) {
+            // If there are more empty processes than our limit on cached
+            // processes, then use the cached process limit for the factor.
+            // This ensures that the really old empty processes get pushed
+            // down to the bottom, so if we are running low on memory we will
+            // have a better chance at keeping around more cached processes
+            // instead of a gazillion empty processes.
+            numEmptyProcs = cachedProcessLimit;
         }
-        for (int i = N - 1; i >= 0; i--) {
-            ProcessRecord app = mProcessList.mLruProcesses.get(i);
-            if (!app.killedByAm && app.thread != null) {
-                app.procStateChanged = false;
-                computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now, false);
+        int cachedFactor = (mNumCachedHiddenProcs > 0 ? (mNumCachedHiddenProcs + mNumSlots - 1) : 1)
+                / mNumSlots;
+        if (cachedFactor < 1) cachedFactor = 1;
 
-                // if any app encountered a cycle, we need to perform an additional loop later
-                retryCycles |= app.containsCycle;
+        int emptyFactor = (numEmptyProcs + mNumSlots - 1) / mNumSlots;
+        if (emptyFactor < 1) emptyFactor = 1;
 
-                // If we haven't yet assigned the final cached adj
-                // to the process, do that now.
-                if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
-                    switch (app.getCurProcState()) {
-                        case PROCESS_STATE_CACHED_ACTIVITY:
-                        case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
-                        case ActivityManager.PROCESS_STATE_CACHED_RECENT:
-                            // Figure out the next cached level, taking into account groups.
-                            boolean inGroup = false;
-                            if (app.connectionGroup != 0) {
-                                if (lastCachedGroupUid == app.uid
-                                        && lastCachedGroup == app.connectionGroup) {
-                                    // This is in the same group as the last process, just tweak
-                                    // adjustment by importance.
-                                    if (app.connectionImportance > lastCachedGroupImportance) {
-                                        lastCachedGroupImportance = app.connectionImportance;
-                                        if (curCachedAdj < nextCachedAdj
-                                                && curCachedAdj < ProcessList.CACHED_APP_MAX_ADJ) {
-                                            curCachedImpAdj++;
-                                        }
-                                    }
-                                    inGroup = true;
-                                } else {
-                                    lastCachedGroupUid = app.uid;
-                                    lastCachedGroup = app.connectionGroup;
+        int stepCached = -1;
+        int stepEmpty = -1;
+        int lastCachedGroup = 0;
+        int lastCachedGroupImportance = 0;
+        int lastCachedGroupUid = 0;
+
+        for (int i = numLru - 1; i >= 0; i--) {
+            ProcessRecord app = lruList.get(i);
+            // If we haven't yet assigned the final cached adj
+            // to the process, do that now.
+            if (!app.killedByAm && app.thread != null && app.curAdj
+                    >= ProcessList.UNKNOWN_ADJ) {
+                switch (app.getCurProcState()) {
+                    case PROCESS_STATE_CACHED_ACTIVITY:
+                    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
+                    case ActivityManager.PROCESS_STATE_CACHED_RECENT:
+                        // Figure out the next cached level, taking into account groups.
+                        boolean inGroup = false;
+                        if (app.connectionGroup != 0) {
+                            if (lastCachedGroupUid == app.uid
+                                    && lastCachedGroup == app.connectionGroup) {
+                                // This is in the same group as the last process, just tweak
+                                // adjustment by importance.
+                                if (app.connectionImportance > lastCachedGroupImportance) {
                                     lastCachedGroupImportance = app.connectionImportance;
-                                }
-                            }
-                            if (!inGroup && curCachedAdj != nextCachedAdj) {
-                                stepCached++;
-                                curCachedImpAdj = 0;
-                                if (stepCached >= cachedFactor) {
-                                    stepCached = 0;
-                                    curCachedAdj = nextCachedAdj;
-                                    nextCachedAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
-                                    if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
-                                        nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
+                                    if (curCachedAdj < nextCachedAdj
+                                            && curCachedAdj < ProcessList.CACHED_APP_MAX_ADJ) {
+                                        curCachedImpAdj++;
                                     }
                                 }
+                                inGroup = true;
+                            } else {
+                                lastCachedGroupUid = app.uid;
+                                lastCachedGroup = app.connectionGroup;
+                                lastCachedGroupImportance = app.connectionImportance;
                             }
-                            // This process is a cached process holding activities...
-                            // assign it the next cached value for that type, and then
-                            // step that cached level.
-                            app.setCurRawAdj(curCachedAdj + curCachedImpAdj);
-                            app.curAdj = app.modifyRawOomAdj(curCachedAdj + curCachedImpAdj);
-                            if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning activity LRU #" + i
+                        }
+                        if (!inGroup && curCachedAdj != nextCachedAdj) {
+                            stepCached++;
+                            curCachedImpAdj = 0;
+                            if (stepCached >= cachedFactor) {
+                                stepCached = 0;
+                                curCachedAdj = nextCachedAdj;
+                                nextCachedAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
+                                if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
+                                    nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
+                                }
+                            }
+                        }
+                        // This process is a cached process holding activities...
+                        // assign it the next cached value for that type, and then
+                        // step that cached level.
+                        app.setCurRawAdj(curCachedAdj + curCachedImpAdj);
+                        app.curAdj = app.modifyRawOomAdj(curCachedAdj + curCachedImpAdj);
+                        if (DEBUG_LRU) {
+                            Slog.d(TAG_LRU, "Assigning activity LRU #" + i
                                     + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
                                     + " curCachedImpAdj=" + curCachedImpAdj + ")");
-                            break;
-                        default:
-                            // Figure out the next cached level.
-                            if (curEmptyAdj != nextEmptyAdj) {
-                                stepEmpty++;
-                                if (stepEmpty >= emptyFactor) {
-                                    stepEmpty = 0;
-                                    curEmptyAdj = nextEmptyAdj;
-                                    nextEmptyAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
-                                    if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
-                                        nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
-                                    }
+                        }
+                        break;
+                    default:
+                        // Figure out the next cached level.
+                        if (curEmptyAdj != nextEmptyAdj) {
+                            stepEmpty++;
+                            if (stepEmpty >= emptyFactor) {
+                                stepEmpty = 0;
+                                curEmptyAdj = nextEmptyAdj;
+                                nextEmptyAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
+                                if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
+                                    nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                 }
                             }
-                            // For everything else, assign next empty cached process
-                            // level and bump that up.  Note that this means that
-                            // long-running services that have dropped down to the
-                            // cached level will be treated as empty (since their process
-                            // state is still as a service), which is what we want.
-                            app.setCurRawAdj(curEmptyAdj);
-                            app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
-                            if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning empty LRU #" + i
+                        }
+                        // For everything else, assign next empty cached process
+                        // level and bump that up.  Note that this means that
+                        // long-running services that have dropped down to the
+                        // cached level will be treated as empty (since their process
+                        // state is still as a service), which is what we want.
+                        app.setCurRawAdj(curEmptyAdj);
+                        app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
+                        if (DEBUG_LRU) {
+                            Slog.d(TAG_LRU, "Assigning empty LRU #" + i
                                     + " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
                                     + ")");
-                            break;
-                    }
+                        }
+                        break;
                 }
             }
         }
+    }
 
-        // Cycle strategy:
-        // - Retry computing any process that has encountered a cycle.
-        // - Continue retrying until no process was promoted.
-        // - Iterate from least important to most important.
-        int cycleCount = 0;
-        while (retryCycles && cycleCount < 10) {
-            cycleCount++;
-            retryCycles = false;
+    private boolean updateAndTrimProcessLocked(final long now, final long nowElapsed,
+            final long oldTime, final ActiveUids activeUids) {
+        ArrayList<ProcessRecord> lruList = mProcessList.mLruProcesses;
+        final int numLru = lruList.size();
 
-            for (int i = 0; i < N; i++) {
-                ProcessRecord app = mProcessList.mLruProcesses.get(i);
-                if (!app.killedByAm && app.thread != null && app.containsCycle == true) {
-                    app.adjSeq--;
-                    app.completedAdjSeq--;
-                }
-            }
+        final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
+        final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
+                - emptyProcessLimit;
+        int lastCachedGroup = 0;
+        int lastCachedGroupUid = 0;
+        int numCached = 0;
+        int numCachedExtraGroup = 0;
+        int numEmpty = 0;
+        int numTrimming = 0;
 
-            for (int i = 0; i < N; i++) {
-                ProcessRecord app = mProcessList.mLruProcesses.get(i);
-                if (!app.killedByAm && app.thread != null && app.containsCycle == true) {
-                    if (computeOomAdjLocked(app, app.getCurRawAdj(), TOP_APP, true, now,
-                            true)) {
-                        retryCycles = true;
-                    }
-                }
-            }
-        }
-
-        lastCachedGroup = lastCachedGroupUid = 0;
-
-        for (int i = N - 1; i >= 0; i--) {
-            ProcessRecord app = mProcessList.mLruProcesses.get(i);
+        for (int i = numLru - 1; i >= 0; i--) {
+            ProcessRecord app = lruList.get(i);
             if (!app.killedByAm && app.thread != null) {
-                applyOomAdjLocked(app, true, now, nowElapsed);
+                // We don't need to apply the update for the process which didn't get computed
+                if (app.completedAdjSeq == mAdjSeq) {
+                    applyOomAdjLocked(app, true, now, nowElapsed);
+                }
 
                 // Count the number of process types.
                 switch (app.getCurProcState()) {
@@ -512,16 +762,7 @@
                     app.kill("isolated not needed", true);
                 } else {
                     // Keeping this process, update its uid.
-                    final UidRecord uidRec = app.uidRecord;
-                    if (uidRec != null) {
-                        uidRec.ephemeral = app.info.isInstantApp();
-                        if (uidRec.getCurProcState() > app.getCurProcState()) {
-                            uidRec.setCurProcState(app.getCurProcState());
-                        }
-                        if (app.hasForegroundServices()) {
-                            uidRec.foregroundServices = true;
-                        }
-                    }
+                    updateAppUidRecLocked(app);
                 }
 
                 if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
@@ -531,31 +772,34 @@
             }
         }
 
-        mService.incrementProcStateSeqAndNotifyAppsLocked();
+        mProcessList.incrementProcStateSeqAndNotifyAppsLocked(activeUids);
 
-        mNumServiceProcs = mNewNumServiceProcs;
+        return mService.updateLowMemStateLocked(numCached, numEmpty, numTrimming);
+    }
 
-        boolean allChanged = mService.updateLowMemStateLocked(numCached, numEmpty, numTrimming);
-
-        if (mService.mAlwaysFinishActivities) {
-            // Need to do this on its own message because the stack may not
-            // be in a consistent state at this point.
-            mService.mAtmInternal.scheduleDestroyAllActivities("always-finish");
+    private void updateAppUidRecLocked(ProcessRecord app) {
+        final UidRecord uidRec = app.uidRecord;
+        if (uidRec != null) {
+            uidRec.ephemeral = app.info.isInstantApp();
+            if (uidRec.getCurProcState() > app.getCurProcState()) {
+                uidRec.setCurProcState(app.getCurProcState());
+            }
+            if (app.hasForegroundServices()) {
+                uidRec.foregroundServices = true;
+            }
         }
+    }
 
-        if (allChanged) {
-            mService.requestPssAllProcsLocked(now, false,
-                    mService.mProcessStats.isMemFactorLowered());
-        }
-
-        ArrayList<UidRecord> becameIdle = null;
+    private void updateUidsLocked(ActiveUids activeUids, final long nowElapsed) {
+        ArrayList<UidRecord> becameIdle = mTmpBecameIdle;
+        becameIdle.clear();
 
         // Update from any uid changes.
         if (mLocalPowerManager != null) {
             mLocalPowerManager.startUidChanges();
         }
-        for (int i = mActiveUids.size() - 1; i >= 0; i--) {
-            final UidRecord uidRec = mActiveUids.valueAt(i);
+        for (int i = activeUids.size() - 1; i >= 0; i--) {
+            final UidRecord uidRec = activeUids.valueAt(i);
             int uidChange = UidRecord.CHANGE_PROCSTATE;
             if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
                     && (uidRec.setProcState != uidRec.getCurProcState()
@@ -582,9 +826,6 @@
                     }
                     if (uidRec.idle && !uidRec.setIdle) {
                         uidChange = UidRecord.CHANGE_IDLE;
-                        if (becameIdle == null) {
-                            becameIdle = new ArrayList<>();
-                        }
                         becameIdle.add(uidRec);
                     }
                 } else {
@@ -617,40 +858,21 @@
             mLocalPowerManager.finishUidChanges();
         }
 
-        if (becameIdle != null) {
+        int size = becameIdle.size();
+        if (size > 0) {
             // If we have any new uids that became idle this time, we need to make sure
             // they aren't left with running services.
-            for (int i = becameIdle.size() - 1; i >= 0; i--) {
+            for (int i = size - 1; i >= 0; i--) {
                 mService.mServices.stopInBackgroundLocked(becameIdle.get(i).uid);
             }
         }
-
-        if (mService.mProcessStats.shouldWriteNowLocked(now)) {
-            mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService,
-                    mService.mProcessStats));
-        }
-
-        // Run this after making sure all procstates are updated.
-        mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now);
-
-        if (DEBUG_OOM_ADJ) {
-            final long duration = SystemClock.uptimeMillis() - now;
-            if (false) {
-                Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms",
-                        new RuntimeException("here").fillInStackTrace());
-            } else {
-                Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms");
-            }
-        }
-        mService.mOomAdjProfiler.oomAdjEnded();
-        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
 
     private final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback =
             new ComputeOomAdjWindowCallback();
 
     /** These methods are called inline during computeOomAdjLocked(), on the same thread */
-    private final class ComputeOomAdjWindowCallback
+    final class ComputeOomAdjWindowCallback
             implements WindowProcessController.ComputeOomAdjCallback {
 
         ProcessRecord app;
@@ -771,7 +993,8 @@
     }
 
     private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
-            ProcessRecord TOP_APP, boolean doingAll, long now, boolean cycleReEval) {
+            ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
+            boolean computeClients) {
         if (mAdjSeq == app.adjSeq) {
             if (app.adjSeq == app.completedAdjSeq) {
                 // This adjustment has already been computed successfully.
@@ -801,7 +1024,6 @@
         app.empty = false;
         app.cached = false;
 
-        final WindowProcessController wpc = app.getWindowProcessController();
         final int appUid = app.info.uid;
         final int logUid = mService.mCurOomAdjUid;
 
@@ -825,7 +1047,7 @@
             // facilitate this, here we need to determine whether or not it
             // is currently showing UI.
             app.systemNoUi = true;
-            if (app == TOP_APP) {
+            if (app == topApp) {
                 app.systemNoUi = false;
                 app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
                 app.adjType = "pers-top-activity";
@@ -833,7 +1055,7 @@
                 // sched group/proc state adjustment is below
                 app.systemNoUi = false;
                 app.adjType = "pers-top-ui";
-            } else if (wpc.hasVisibleActivities()) {
+            } else if (app.getCachedHasVisibleActivities()) {
                 app.systemNoUi = false;
             }
             if (!app.systemNoUi) {
@@ -866,8 +1088,7 @@
         int cachedAdjSeq;
 
         boolean foregroundActivities = false;
-        mTmpBroadcastQueue.clear();
-        if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == TOP_APP) {
+        if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) {
             // The last app on the list is the foreground app.
             adj = ProcessList.FOREGROUND_APP_ADJ;
             schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
@@ -894,7 +1115,7 @@
             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app);
             }
-        } else if (mService.isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
+        } else if (app.getCachedIsReceivingBroadcast(mTmpBroadcastQueue)) {
             // An app that is currently receiving a broadcast also
             // counts as being in the foreground for OOM killer purposes.
             // It's placed in a sched group based on the nature of the
@@ -919,7 +1140,7 @@
                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making exec-service: " + app);
             }
             //Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);
-        } else if (app == TOP_APP) {
+        } else if (app == topApp) {
             adj = ProcessList.FOREGROUND_APP_ADJ;
             schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
             app.adjType = "top-sleeping";
@@ -944,24 +1165,19 @@
         }
 
         // Examine all activities if not already foreground.
-        if (!foregroundActivities && wpc.hasActivities()) {
-            mTmpComputeOomAdjWindowCallback.initialize(app, adj, foregroundActivities, procState,
-                    schedGroup, appUid, logUid, PROCESS_STATE_CUR_TOP);
-            final int minLayer = wpc.computeOomAdjFromActivities(
-                    ProcessList.VISIBLE_APP_LAYER_MAX, mTmpComputeOomAdjWindowCallback);
+        if (!foregroundActivities && app.getCachedHasActivities()) {
+            app.computeOomAdjFromActivitiesIfNecessary(mTmpComputeOomAdjWindowCallback,
+                    adj, foregroundActivities, procState, schedGroup, appUid, logUid,
+                    PROCESS_STATE_CUR_TOP);
 
-            adj = mTmpComputeOomAdjWindowCallback.adj;
-            foregroundActivities = mTmpComputeOomAdjWindowCallback.foregroundActivities;
-            procState = mTmpComputeOomAdjWindowCallback.procState;
-            schedGroup = mTmpComputeOomAdjWindowCallback.schedGroup;
-
-            if (adj == ProcessList.VISIBLE_APP_ADJ) {
-                adj += minLayer;
-            }
+            adj = app.mCachedAdj;
+            foregroundActivities = app.mCachedForegroundActivities;
+            procState = app.mCachedProcState;
+            schedGroup = app.mCachedSchedGroup;
         }
 
-        if (procState > ActivityManager.PROCESS_STATE_CACHED_RECENT && app.hasRecentTasks()) {
-            procState = ActivityManager.PROCESS_STATE_CACHED_RECENT;
+        if (procState > PROCESS_STATE_CACHED_RECENT && app.getCachedHasRecentTasks()) {
+            procState = PROCESS_STATE_CACHED_RECENT;
             app.adjType = "cch-rec";
             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to cached recent: " + app);
@@ -1031,7 +1247,7 @@
             }
         }
 
-        if (mService.mAtmInternal.isHeavyWeightProcess(app.getWindowProcessController())) {
+        if (app.getCachedIsHeavyWeight()) {
             if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
                 // We don't want to kill the current heavy-weight process.
                 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
@@ -1051,7 +1267,7 @@
             }
         }
 
-        if (wpc.isHomeProcess()) {
+        if (app.getCachedIsHomeProcess()) {
             if (adj > ProcessList.HOME_APP_ADJ) {
                 // This process is hosting what we currently consider to be the
                 // home app, so we don't want to let it go into the background.
@@ -1072,7 +1288,7 @@
             }
         }
 
-        if (wpc.isPreviousProcess() && app.hasActivities()) {
+        if (app.getCachedIsPreviousProcess() && app.getCachedHasActivities()) {
             if (adj > ProcessList.PREVIOUS_APP_ADJ) {
                 // This was the previous process that showed UI to the user.
                 // We want to try to keep it around more aggressively, to give
@@ -1153,7 +1369,7 @@
                                 "Raise procstate to started service: " + app);
                     }
                 }
-                if (app.hasShownUi && !wpc.isHomeProcess()) {
+                if (app.hasShownUi && !app.getCachedIsHomeProcess()) {
                     // If this process has shown some UI, let it immediately
                     // go to the LRU list because it may be pretty heavy with
                     // UI stuff.  We'll tag it with a label just to help
@@ -1208,7 +1424,13 @@
                     boolean trackedProcState = false;
                     if ((cr.flags& Context.BIND_WAIVE_PRIORITY) == 0) {
                         ProcessRecord client = cr.binding.client;
-                        computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now, cycleReEval);
+                        if (computeClients) {
+                            computeOomAdjLocked(client, cachedAdj, topApp, doingAll, now,
+                                    cycleReEval, true);
+                        } else {
+                            client.setCurRawAdj(client.setAdj);
+                            client.setCurRawProcState(client.setProcState);
+                        }
 
                         if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) {
                             continue;
@@ -1227,7 +1449,7 @@
                         if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
                             // Not doing bind OOM management, so treat
                             // this guy more like a started service.
-                            if (app.hasShownUi && !wpc.isHomeProcess()) {
+                            if (app.hasShownUi && !app.getCachedIsHomeProcess()) {
                                 // If this process has shown some UI, let it immediately
                                 // go to the LRU list because it may be pretty heavy with
                                 // UI stuff.  We'll tag it with a label just to help
@@ -1261,7 +1483,7 @@
                             // about letting this process get into the LRU
                             // list to be killed and restarted if needed for
                             // memory.
-                            if (app.hasShownUi && !wpc.isHomeProcess()
+                            if (app.hasShownUi && !app.getCachedIsHomeProcess()
                                     && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                 if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
                                     adjType = "cch-bound-ui-services";
@@ -1451,7 +1673,13 @@
                     // Being our own client is not interesting.
                     continue;
                 }
-                computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now, cycleReEval);
+                if (computeClients) {
+                    computeOomAdjLocked(client, cachedAdj, topApp, doingAll, now, cycleReEval,
+                            true);
+                } else {
+                    client.setCurRawAdj(client.setAdj);
+                    client.setCurRawProcState(client.setProcState);
+                }
 
                 if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) {
                     continue;
@@ -1467,7 +1695,7 @@
                 }
                 String adjType = null;
                 if (adj > clientAdj) {
-                    if (app.hasShownUi && !wpc.isHomeProcess()
+                    if (app.hasShownUi && !app.getCachedIsHomeProcess()
                             && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                         adjType = "cch-ui-provider";
                     } else {
@@ -1565,7 +1793,7 @@
         if (procState >= PROCESS_STATE_CACHED_EMPTY) {
             if (app.hasClientActivities()) {
                 // This is a cached process, but with client activities.  Mark it so.
-                procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
+                procState = PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
                 app.adjType = "cch-client-act";
             } else if (app.treatLikeActivity) {
                 // This is a cached process, but somebody wants us to treat it like it has
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index af126f2..8163a6d 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -20,6 +20,8 @@
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
 import static android.os.Process.getFreeMemory;
@@ -28,6 +30,7 @@
 import static android.os.Process.startWebView;
 
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_NETWORK;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS;
@@ -41,6 +44,7 @@
 import static com.android.server.am.ActivityManagerService.PROC_START_TIMEOUT_WITH_WRAPPER;
 import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
 import static com.android.server.am.ActivityManagerService.TAG_LRU;
+import static com.android.server.am.ActivityManagerService.TAG_NETWORK;
 import static com.android.server.am.ActivityManagerService.TAG_PROCESSES;
 import static com.android.server.am.ActivityManagerService.TAG_PSS;
 import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS;
@@ -240,6 +244,24 @@
     // Threshold of number of cached+empty where we consider memory critical.
     static final int TRIM_LOW_THRESHOLD = 5;
 
+    /**
+     * State indicating that there is no need for any blocking for network.
+     */
+    @VisibleForTesting
+    static final int NETWORK_STATE_NO_CHANGE = 0;
+
+    /**
+     * State indicating that the main thread needs to be informed about the network wait.
+     */
+    @VisibleForTesting
+    static final int NETWORK_STATE_BLOCK = 1;
+
+    /**
+     * State indicating that any threads waiting for network state to get updated can be unblocked.
+     */
+    @VisibleForTesting
+    static final int NETWORK_STATE_UNBLOCK = 2;
+
     // If true, then we pass the flag to ART to load the app image startup cache.
     private static final String PROPERTY_USE_APP_IMAGE_STARTUP_CACHE =
             "persist.device_config.runtime_native.use_app_image_startup_cache";
@@ -3189,4 +3211,113 @@
             mService.doStopUidLocked(uidRec.uid, uidRec);
         }
     }
+
+    /**
+     * Checks if the uid is coming from background to foreground or vice versa and returns
+     * appropriate block state based on this.
+     *
+     * @return blockState based on whether the uid is coming from background to foreground or
+     *         vice versa. If bg->fg or fg->bg, then {@link #NETWORK_STATE_BLOCK} or
+     *         {@link #NETWORK_STATE_UNBLOCK} respectively, otherwise
+     *         {@link #NETWORK_STATE_NO_CHANGE}.
+     */
+    @VisibleForTesting
+    int getBlockStateForUid(UidRecord uidRec) {
+        // Denotes whether uid's process state is currently allowed network access.
+        final boolean isAllowed =
+                isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.getCurProcState())
+                || isProcStateAllowedWhileOnRestrictBackground(uidRec.getCurProcState());
+        // Denotes whether uid's process state was previously allowed network access.
+        final boolean wasAllowed = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.setProcState)
+                || isProcStateAllowedWhileOnRestrictBackground(uidRec.setProcState);
+
+        // When the uid is coming to foreground, AMS should inform the app thread that it should
+        // block for the network rules to get updated before launching an activity.
+        if (!wasAllowed && isAllowed) {
+            return NETWORK_STATE_BLOCK;
+        }
+        // When the uid is going to background, AMS should inform the app thread that if an
+        // activity launch is blocked for the network rules to get updated, it should be unblocked.
+        if (wasAllowed && !isAllowed) {
+            return NETWORK_STATE_UNBLOCK;
+        }
+        return NETWORK_STATE_NO_CHANGE;
+    }
+
+    /**
+     * Checks if any uid is coming from background to foreground or vice versa and if so, increments
+     * the {@link UidRecord#curProcStateSeq} corresponding to that uid using global seq counter
+     * {@link ProcessList#mProcStateSeqCounter} and notifies the app if it needs to block.
+     */
+    @VisibleForTesting
+    @GuardedBy("mService")
+    void incrementProcStateSeqAndNotifyAppsLocked(ActiveUids activeUids) {
+        if (mService.mWaitForNetworkTimeoutMs <= 0) {
+            return;
+        }
+        // Used for identifying which uids need to block for network.
+        ArrayList<Integer> blockingUids = null;
+        for (int i = activeUids.size() - 1; i >= 0; --i) {
+            final UidRecord uidRec = activeUids.valueAt(i);
+            // If the network is not restricted for uid, then nothing to do here.
+            if (!mService.mInjector.isNetworkRestrictedForUid(uidRec.uid)) {
+                continue;
+            }
+            if (!UserHandle.isApp(uidRec.uid) || !uidRec.hasInternetPermission) {
+                continue;
+            }
+            // If process state is not changed, then there's nothing to do.
+            if (uidRec.setProcState == uidRec.getCurProcState()) {
+                continue;
+            }
+            final int blockState = getBlockStateForUid(uidRec);
+            // No need to inform the app when the blockState is NETWORK_STATE_NO_CHANGE as
+            // there's nothing the app needs to do in this scenario.
+            if (blockState == NETWORK_STATE_NO_CHANGE) {
+                continue;
+            }
+            synchronized (uidRec.networkStateLock) {
+                uidRec.curProcStateSeq = ++mProcStateSeqCounter; // TODO: use method
+                if (blockState == NETWORK_STATE_BLOCK) {
+                    if (blockingUids == null) {
+                        blockingUids = new ArrayList<>();
+                    }
+                    blockingUids.add(uidRec.uid);
+                } else {
+                    if (DEBUG_NETWORK) {
+                        Slog.d(TAG_NETWORK, "uid going to background, notifying all blocking"
+                                + " threads for uid: " + uidRec);
+                    }
+                    if (uidRec.waitingForNetwork) {
+                        uidRec.networkStateLock.notifyAll();
+                    }
+                }
+            }
+        }
+
+        // There are no uids that need to block, so nothing more to do.
+        if (blockingUids == null) {
+            return;
+        }
+
+        for (int i = mLruProcesses.size() - 1; i >= 0; --i) {
+            final ProcessRecord app = mLruProcesses.get(i);
+            if (!blockingUids.contains(app.uid)) {
+                continue;
+            }
+            if (!app.killedByAm && app.thread != null) {
+                final UidRecord uidRec = getUidRecordLocked(app.uid);
+                try {
+                    if (DEBUG_NETWORK) {
+                        Slog.d(TAG_NETWORK, "Informing app thread that it needs to block: "
+                                + uidRec);
+                    }
+                    if (uidRec != null) {
+                        app.thread.setNetworkBlockSeq(uidRec.curProcStateSeq);
+                    }
+                } catch (RemoteException ignored) {
+                }
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index ea30842..bf43f3b 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -308,6 +308,22 @@
     // This will be same as {@link #uid} usually except for some apps used during factory testing.
     int startUid;
 
+    // Cached task info for OomAdjuster
+    private static final int VALUE_INVALID = -1;
+    private static final int VALUE_FALSE = 0;
+    private static final int VALUE_TRUE = 1;
+    private int mCachedHasActivities = VALUE_INVALID;
+    private int mCachedIsHeavyWeight = VALUE_INVALID;
+    private int mCachedHasVisibleActivities = VALUE_INVALID;
+    private int mCachedIsHomeProcess = VALUE_INVALID;
+    private int mCachedIsPreviousProcess = VALUE_INVALID;
+    private int mCachedHasRecentTasks = VALUE_INVALID;
+    private int mCachedIsReceivingBroadcast = VALUE_INVALID;
+    int mCachedAdj = ProcessList.INVALID_ADJ;
+    boolean mCachedForegroundActivities = false;
+    int mCachedProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+    int mCachedSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
+
     void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
             long startTime) {
         this.startUid = startUid;
@@ -1302,7 +1318,7 @@
             }
             mService.mProcessList.updateLruProcessLocked(this, activityChange, null /* client */);
             if (updateOomAdj) {
-                mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_ACTIVITY);
+                mService.updateOomAdjLocked(this, OomAdjuster.OOM_ADJ_REASON_ACTIVITY);
             }
         }
     }
@@ -1650,4 +1666,100 @@
         return Settings.Secure.getInt(mService.mContext.getContentResolver(),
                 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
     }
+
+    void resetCachedInfo() {
+        mCachedHasActivities = VALUE_INVALID;
+        mCachedIsHeavyWeight = VALUE_INVALID;
+        mCachedHasVisibleActivities = VALUE_INVALID;
+        mCachedIsHomeProcess = VALUE_INVALID;
+        mCachedIsPreviousProcess = VALUE_INVALID;
+        mCachedHasRecentTasks = VALUE_INVALID;
+        mCachedIsReceivingBroadcast = VALUE_INVALID;
+        mCachedAdj = ProcessList.INVALID_ADJ;
+        mCachedForegroundActivities = false;
+        mCachedProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+        mCachedSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
+    }
+
+    boolean getCachedHasActivities() {
+        if (mCachedHasActivities == VALUE_INVALID) {
+            mCachedHasActivities = getWindowProcessController().hasActivities() ? VALUE_TRUE
+                    : VALUE_FALSE;
+        }
+        return mCachedHasActivities == VALUE_TRUE;
+    }
+
+    boolean getCachedIsHeavyWeight() {
+        if (mCachedIsHeavyWeight == VALUE_INVALID) {
+            mCachedIsHeavyWeight = mService.mAtmInternal.isHeavyWeightProcess(
+                    getWindowProcessController()) ? VALUE_TRUE : VALUE_FALSE;
+        }
+        return mCachedIsHeavyWeight == VALUE_TRUE;
+    }
+
+    boolean getCachedHasVisibleActivities() {
+        if (mCachedHasVisibleActivities == VALUE_INVALID) {
+            mCachedHasVisibleActivities = getWindowProcessController().hasVisibleActivities()
+                    ? VALUE_TRUE : VALUE_FALSE;
+        }
+        return mCachedHasVisibleActivities == VALUE_TRUE;
+    }
+
+    boolean getCachedIsHomeProcess() {
+        if (mCachedIsHomeProcess == VALUE_INVALID) {
+            mCachedIsHomeProcess = getWindowProcessController().isHomeProcess()
+                    ? VALUE_TRUE : VALUE_FALSE;
+        }
+        return mCachedIsHomeProcess == VALUE_TRUE;
+    }
+
+    boolean getCachedIsPreviousProcess() {
+        if (mCachedIsPreviousProcess == VALUE_INVALID) {
+            mCachedIsPreviousProcess = getWindowProcessController().isPreviousProcess()
+                    ? VALUE_TRUE : VALUE_FALSE;
+        }
+        return mCachedIsPreviousProcess == VALUE_TRUE;
+    }
+
+    boolean getCachedHasRecentTasks() {
+        if (mCachedHasRecentTasks == VALUE_INVALID) {
+            mCachedHasRecentTasks = getWindowProcessController().hasRecentTasks()
+                    ? VALUE_TRUE : VALUE_FALSE;
+        }
+        return mCachedHasRecentTasks == VALUE_TRUE;
+    }
+
+    boolean getCachedIsReceivingBroadcast(ArraySet<BroadcastQueue> tmpQueue) {
+        if (mCachedIsReceivingBroadcast == VALUE_INVALID) {
+            tmpQueue.clear();
+            mCachedIsReceivingBroadcast = mService.isReceivingBroadcastLocked(this, tmpQueue)
+                    ? VALUE_TRUE : VALUE_FALSE;
+            if (mCachedIsReceivingBroadcast == VALUE_TRUE) {
+                mCachedSchedGroup = tmpQueue.contains(mService.mFgBroadcastQueue)
+                        ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
+            }
+        }
+        return mCachedIsReceivingBroadcast == VALUE_TRUE;
+    }
+
+    void computeOomAdjFromActivitiesIfNecessary(OomAdjuster.ComputeOomAdjWindowCallback callback,
+            int adj, boolean foregroundActivities, int procState, int schedGroup, int appUid,
+            int logUid, int processCurTop) {
+        if (mCachedAdj != ProcessList.INVALID_ADJ) {
+            return;
+        }
+        callback.initialize(this, adj, foregroundActivities, procState, schedGroup, appUid, logUid,
+                processCurTop);
+        final int minLayer = getWindowProcessController().computeOomAdjFromActivities(
+                ProcessList.VISIBLE_APP_LAYER_MAX, callback);
+
+        mCachedAdj = callback.adj;
+        mCachedForegroundActivities = callback.foregroundActivities;
+        mCachedProcState = callback.procState;
+        mCachedSchedGroup = callback.schedGroup;
+
+        if (mCachedAdj == ProcessList.VISIBLE_APP_ADJ) {
+            mCachedAdj += minLayer;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java
index 98f5557..bbf5772 100644
--- a/services/core/java/com/android/server/am/UserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java
@@ -78,7 +78,7 @@
 
         WindowManager.LayoutParams attrs = getWindow().getAttributes();
         attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR |
-            WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+            WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         getWindow().setAttributes(attrs);
     }
 
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 6c4cc2d..8575068 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -47,6 +47,7 @@
 import android.app.AppOpsManager.HistoricalOps;
 import android.app.AppOpsManager.HistoricalOpsRequest;
 import android.app.AppOpsManager.Mode;
+import android.app.AppOpsManager.OpFeatureEntry;
 import android.app.AppOpsManager.OpEntry;
 import android.app.AppOpsManager.OpFlags;
 import android.app.AppOpsManagerInternal;
@@ -68,6 +69,7 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -140,6 +142,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 public class AppOpsService extends IAppOpsService.Stub {
     static final String TAG = "AppOps";
@@ -362,7 +365,9 @@
         public int pendingState = UID_STATE_CACHED;
         public long pendingStateCommitTime;
 
+        // For all features combined
         public int startNesting;
+
         public ArrayMap<String, Ops> pkgOps;
         public SparseIntArray opModes;
 
@@ -452,21 +457,133 @@
         }
     }
 
-    final static class Op {
-        int op;
-        boolean running;
-        final UidState uidState;
-        final @NonNull String packageName;
+    private static final class FeatureOp {
+        public final @NonNull Op parent;
 
-        private @Mode int mode;
+        public boolean running;
+
         private @Nullable LongSparseLongArray mAccessTimes;
         private @Nullable LongSparseLongArray mRejectTimes;
         private @Nullable LongSparseLongArray mDurations;
         private @Nullable LongSparseLongArray mProxyUids;
+        private @Nullable LongSparseArray<String> mProxyFeatureIds;
         private @Nullable LongSparseArray<String> mProxyPackageNames;
 
-        int startNesting;
-        long startRealtime;
+        public int startNesting;
+        public long startRealtime;
+
+        FeatureOp(@NonNull Op parent) {
+            this.parent = parent;
+        }
+
+        public void accessed(long time, int proxyUid, @Nullable String proxyPackageName,
+                @Nullable String proxyFeatureId, @AppOpsManager.UidState int uidState,
+                @OpFlags int flags) {
+            final long key = AppOpsManager.makeKey(uidState, flags);
+            if (mAccessTimes == null) {
+                mAccessTimes = new LongSparseLongArray();
+            }
+            mAccessTimes.put(key, time);
+            updateProxyState(key, proxyUid, proxyPackageName, proxyFeatureId);
+            if (mDurations != null) {
+                mDurations.delete(key);
+            }
+        }
+
+        public void rejected(long time, int proxyUid, @Nullable String proxyPackageName,
+                @Nullable String proxyFeatureId, @AppOpsManager.UidState int uidState,
+                @OpFlags int flags) {
+            final long key = AppOpsManager.makeKey(uidState, flags);
+            if (mRejectTimes == null) {
+                mRejectTimes = new LongSparseLongArray();
+            }
+            mRejectTimes.put(key, time);
+            updateProxyState(key, proxyUid, proxyPackageName, proxyFeatureId);
+            if (mDurations != null) {
+                mDurations.delete(key);
+            }
+        }
+
+        public void started(long time, @AppOpsManager.UidState int uidState, @OpFlags int flags) {
+            updateAccessTimeAndDuration(time, -1 /*duration*/, uidState, flags);
+            running = true;
+        }
+
+        public void finished(long time, long duration, @AppOpsManager.UidState int uidState,
+                @OpFlags int flags) {
+            updateAccessTimeAndDuration(time, duration, uidState, flags);
+            running = false;
+        }
+
+        public void running(long time, long duration, @AppOpsManager.UidState int uidState,
+                @OpFlags int flags) {
+            updateAccessTimeAndDuration(time, duration, uidState, flags);
+        }
+
+        public void continuing(long duration, @AppOpsManager.UidState int uidState,
+                @OpFlags int flags) {
+            final long key = AppOpsManager.makeKey(uidState, flags);
+            if (mDurations == null) {
+                mDurations = new LongSparseLongArray();
+            }
+            mDurations.put(key, duration);
+        }
+
+        private void updateAccessTimeAndDuration(long time, long duration,
+                @AppOpsManager.UidState int uidState, @OpFlags int flags) {
+            final long key = AppOpsManager.makeKey(uidState, flags);
+            if (mAccessTimes == null) {
+                mAccessTimes = new LongSparseLongArray();
+            }
+            mAccessTimes.put(key, time);
+            if (mDurations == null) {
+                mDurations = new LongSparseLongArray();
+            }
+            mDurations.put(key, duration);
+        }
+
+        private void updateProxyState(long key, int proxyUid,
+                @Nullable String proxyPackageName, @Nullable String featureId) {
+            if (proxyUid == Process.INVALID_UID) {
+                return;
+            }
+
+            if (mProxyUids == null) {
+                mProxyUids = new LongSparseLongArray();
+            }
+            mProxyUids.put(key, proxyUid);
+
+            if (mProxyPackageNames == null) {
+                mProxyPackageNames = new LongSparseArray<>();
+            }
+            mProxyPackageNames.put(key, proxyPackageName);
+
+            if (mProxyFeatureIds == null) {
+                mProxyFeatureIds = new LongSparseArray<>();
+            }
+            mProxyFeatureIds.put(key, featureId);
+        }
+
+        boolean hasAnyTime() {
+            return (mAccessTimes != null && mAccessTimes.size() > 0)
+                    || (mRejectTimes != null && mRejectTimes.size() > 0);
+        }
+
+        @NonNull OpFeatureEntry.Builder createFeatureEntryBuilderLocked() {
+            return new OpFeatureEntry.Builder(running, mAccessTimes, mRejectTimes, mDurations,
+                    mProxyUids, mProxyPackageNames, mProxyFeatureIds);
+        }
+    }
+
+    final static class Op {
+        int op;
+        final UidState uidState;
+        final @NonNull String packageName;
+
+        private @Mode int mode;
+
+        /** featureId -> FeatureOp */
+        final ArrayMap<String, FeatureOp> mFeatures = new ArrayMap<>(1);
 
         Op(UidState uidState, String packageName, int op) {
             this.op = op;
@@ -483,95 +600,54 @@
             return uidState.evalMode(op, mode);
         }
 
-        /** @hide */
-        public void accessed(long time, int proxyUid, @Nullable String proxyPackageName,
-            @AppOpsManager.UidState int uidState, @OpFlags int flags) {
-            final long key = AppOpsManager.makeKey(uidState, flags);
-            if (mAccessTimes == null) {
-                mAccessTimes = new LongSparseLongArray();
-            }
-            mAccessTimes.put(key, time);
-            updateProxyState(key, proxyUid, proxyPackageName);
-            if (mDurations != null) {
-                mDurations.delete(key);
+        void removeFeaturesWithNoTime() {
+            for (int i = mFeatures.size() - 1; i >= 0; i--) {
+                if (!mFeatures.valueAt(i).hasAnyTime()) {
+                    mFeatures.removeAt(i);
+                }
             }
         }
 
-        /** @hide */
-        public void rejected(long time, int proxyUid, @Nullable String proxyPackageName,
-            @AppOpsManager.UidState int uidState, @OpFlags int flags) {
-            final long key = AppOpsManager.makeKey(uidState, flags);
-            if (mRejectTimes == null) {
-                mRejectTimes = new LongSparseLongArray();
+        private @NonNull FeatureOp getOrCreateFeature(@NonNull Op parent,
+                @Nullable String featureId) {
+            FeatureOp featureOp;
+
+            featureOp = mFeatures.get(featureId);
+            if (featureOp == null) {
+                featureOp = new FeatureOp(parent);
+                mFeatures.put(featureId, featureOp);
             }
-            mRejectTimes.put(key, time);
-            updateProxyState(key, proxyUid, proxyPackageName);
-            if (mDurations != null) {
-                mDurations.delete(key);
-            }
+
+            return featureOp;
         }
 
-        /** @hide */
-        public void started(long time, @AppOpsManager.UidState int uidState, @OpFlags int flags) {
-            updateAccessTimeAndDuration(time, -1 /*duration*/, uidState, flags);
-            running = true;
-        }
+        @NonNull OpEntry createEntryLocked() {
+            final int numFeatures = mFeatures.size();
 
-        /** @hide */
-        public void finished(long time, long duration, @AppOpsManager.UidState int uidState,
-            @OpFlags int flags) {
-            updateAccessTimeAndDuration(time, duration, uidState, flags);
-            running = false;
-        }
-
-        /** @hide */
-        public void running(long time, long duration, @AppOpsManager.UidState int uidState,
-            @OpFlags int flags) {
-            updateAccessTimeAndDuration(time, duration, uidState, flags);
-        }
-
-        /** @hide */
-        public void continuing(long duration, @AppOpsManager.UidState int uidState,
-            @OpFlags int flags) {
-            final long key = AppOpsManager.makeKey(uidState, flags);
-            if (mDurations == null) {
-                mDurations = new LongSparseLongArray();
-            }
-            mDurations.put(key, duration);
-        }
-
-        private void updateAccessTimeAndDuration(long time, long duration,
-            @AppOpsManager.UidState int uidState, @OpFlags int flags) {
-            final long key = AppOpsManager.makeKey(uidState, flags);
-            if (mAccessTimes == null) {
-                mAccessTimes = new LongSparseLongArray();
-            }
-            mAccessTimes.put(key, time);
-            if (mDurations == null) {
-                mDurations = new LongSparseLongArray();
-            }
-            mDurations.put(key, duration);
-        }
-
-        private void updateProxyState(long key, int proxyUid,
-            @Nullable String proxyPackageName) {
-            if (proxyUid == Process.INVALID_UID) {
-                return;
+            final Pair<String, OpFeatureEntry.Builder>[] featureEntries =
+                    new Pair[numFeatures];
+            for (int i = 0; i < numFeatures; i++) {
+                featureEntries[i] = new Pair<>(mFeatures.keyAt(i),
+                        mFeatures.valueAt(i).createFeatureEntryBuilderLocked());
             }
 
-            if (mProxyUids == null) {
-                mProxyUids = new LongSparseLongArray();
-            }
-            mProxyUids.put(key, proxyUid);
-            if (mProxyPackageNames == null) {
-                mProxyPackageNames = new LongSparseArray<>();
-            }
-            mProxyPackageNames.put(key, proxyPackageName);
+            return new OpEntry(op, mode, featureEntries);
         }
 
-        boolean hasAnyTime() {
-            return (mAccessTimes != null && mAccessTimes.size() > 0)
-                || (mRejectTimes != null && mRejectTimes.size() > 0);
+        @NonNull OpEntry createSingleFeatureEntryLocked(@Nullable String featureId) {
+            final int numFeatures = mFeatures.size();
+
+            final Pair<String, AppOpsManager.OpFeatureEntry.Builder>[] featureEntries =
+                    new Pair[1];
+            for (int i = 0; i < numFeatures; i++) {
+                if (Objects.equals(mFeatures.keyAt(i), featureId)) {
+                    featureEntries[0] = new Pair<>(mFeatures.keyAt(i),
+                            mFeatures.valueAt(i).createFeatureEntryBuilderLocked());
+                    break;
+                }
+            }
+
+            return new OpEntry(op, mode, featureEntries);
         }
     }
 
@@ -725,7 +801,7 @@
     final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<>();
 
     final class ClientState extends Binder implements DeathRecipient {
-        final ArrayList<Op> mStartedOps = new ArrayList<>();
+        final ArrayList<Pair<Op, String>> mStartedOps = new ArrayList<>();
         final IBinder mAppToken;
         final int mPid;
 
@@ -754,9 +830,12 @@
         public void binderDied() {
             synchronized (AppOpsService.this) {
                 for (int i=mStartedOps.size()-1; i>=0; i--) {
-                    final Op op = mStartedOps.get(i);
-                    finishOperationLocked(op, /*finishNested*/ true);
-                    if (op.startNesting <= 0) {
+                    final Pair<Op, String> startedOp = mStartedOps.get(i);
+                    final Op op = startedOp.first;
+                    final String featureId = startedOp.second;
+
+                    finishOperationLocked(op, featureId, /*finishNested*/ true);
+                    if (op.mFeatures.get(featureId).startNesting <= 0) {
                         scheduleOpActiveChangedIfNeededLocked(op.op, op.uidState.uid,
                                 op.packageName, false);
                     }
@@ -888,11 +967,11 @@
                                 return Zygote.MOUNT_EXTERNAL_NONE;
                             }
                             if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid,
-                                    packageName) != AppOpsManager.MODE_ALLOWED) {
+                                    packageName, null) != AppOpsManager.MODE_ALLOWED) {
                                 return Zygote.MOUNT_EXTERNAL_NONE;
                             }
                             if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid,
-                                    packageName) != AppOpsManager.MODE_ALLOWED) {
+                                    packageName, null) != AppOpsManager.MODE_ALLOWED) {
                                 return Zygote.MOUNT_EXTERNAL_READ;
                             }
                             return Zygote.MOUNT_EXTERNAL_WRITE;
@@ -935,13 +1014,16 @@
                 if (client.mStartedOps == null) {
                     continue;
                 }
-                final int opCount = client.mStartedOps.size();
-                for (int j = opCount - 1; j >= 0; j--) {
-                    final Op op = client.mStartedOps.get(j);
+                final int startedOpCount = client.mStartedOps.size();
+                for (int j = startedOpCount - 1; j >= 0; j--) {
+                    final Pair<Op, String> startedOp = client.mStartedOps.get(j);
+                    final Op op = startedOp.first;
+                    final String featureId = startedOp.second;
+
                     if (uid == op.uidState.uid && packageName.equals(op.packageName)) {
-                        finishOperationLocked(op, /*finishNested*/ true);
+                        finishOperationLocked(op, featureId, /*finishNested*/ true);
                         client.mStartedOps.remove(j);
-                        if (op.startNesting <= 0) {
+                        if (op.mFeatures.get(featureId).startNesting <= 0) {
                             scheduleOpActiveChangedIfNeededLocked(op.op,
                                     uid, packageName, false);
                         }
@@ -953,11 +1035,16 @@
                 scheduleFastWriteLocked();
 
                 final int opCount = ops.size();
-                for (int i = 0; i < opCount; i++) {
-                    final Op op = ops.valueAt(i);
-                    if (op.running) {
-                        scheduleOpActiveChangedIfNeededLocked(
-                                op.op, op.uidState.uid, op.packageName, false);
+                for (int opNum = 0; opNum < opCount; opNum++) {
+                    final Op op = ops.valueAt(opNum);
+
+                    final int numFeatures = op.mFeatures.size();
+                    for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
+                        if (op.mFeatures.valueAt(featureNum).running) {
+                            scheduleOpActiveChangedIfNeededLocked(
+                                    op.op, op.uidState.uid, op.packageName, false);
+                            break;
+                        }
                     }
                 }
             }
@@ -1010,19 +1097,26 @@
                         final Ops ops = uidState.pkgOps.valueAt(i);
                         for (int j = ops.size() - 1; j >= 0; j--) {
                             final Op op = ops.valueAt(j);
-                            if (op.startNesting > 0) {
-                                final long duration = SystemClock.elapsedRealtime()
-                                        - op.startRealtime;
-                                // We don't support proxy long running ops (start/stop)
-                                mHistoricalRegistry.increaseOpAccessDuration(op.op,
-                                        op.uidState.uid, op.packageName, oldPendingState,
-                                        AppOpsManager.OP_FLAG_SELF, duration);
-                                // Finish the op in the old state
-                                op.finished(now, duration, oldPendingState,
-                                        AppOpsManager.OP_FLAG_SELF);
-                                // Start the op in the new state
-                                op.startRealtime = now;
-                                op.started(now, newState, AppOpsManager.OP_FLAG_SELF);
+
+                            int numFeatures = op.mFeatures.size();
+                            for (int featureNum = 0; featureNum < numFeatures;
+                                    featureNum++) {
+                                final FeatureOp featureOp = op.mFeatures.valueAt(
+                                        featureNum);
+                                if (featureOp.startNesting > 0) {
+                                    final long duration = SystemClock.elapsedRealtime()
+                                            - featureOp.startRealtime;
+                                    // We don't support proxy long running ops (start/stop)
+                                    mHistoricalRegistry.increaseOpAccessDuration(op.op,
+                                            op.uidState.uid, op.packageName, oldPendingState,
+                                            AppOpsManager.OP_FLAG_SELF, duration);
+                                    // Finish the op in the old state
+                                    featureOp.finished(now, duration, oldPendingState,
+                                            AppOpsManager.OP_FLAG_SELF);
+                                    // Start the op in the new state
+                                    featureOp.startRealtime = now;
+                                    featureOp.started(now, newState, AppOpsManager.OP_FLAG_SELF);
+                                }
                             }
                         }
                     }
@@ -1068,24 +1162,32 @@
         return resOps;
     }
 
-    private ArrayList<AppOpsManager.OpEntry> collectOps(SparseIntArray uidOps, int[] ops) {
-        if (uidOps == null) {
+    @Nullable
+    private ArrayList<AppOpsManager.OpEntry> collectUidOps(@NonNull UidState uidState,
+            @Nullable int[] ops) {
+        if (uidState.opModes == null) {
+            return null;
+        }
+
+        int opModeCount = uidState.opModes.size();
+        if (opModeCount == 0) {
             return null;
         }
         ArrayList<AppOpsManager.OpEntry> resOps = null;
         if (ops == null) {
             resOps = new ArrayList<>();
-            for (int j=0; j<uidOps.size(); j++) {
-                resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
+            for (int i = 0; i < opModeCount; i++) {
+                int code = uidState.opModes.keyAt(i);
+                resOps.add(new OpEntry(code, uidState.opModes.get(code), new Pair[0]));
             }
         } else {
             for (int j=0; j<ops.length; j++) {
-                int index = uidOps.indexOfKey(ops[j]);
-                if (index >= 0) {
+                int code = uidState.opModes.keyAt(j);
+                if (code >= 0) {
                     if (resOps == null) {
                         resOps = new ArrayList<>();
                     }
-                    resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
+                    resOps.add(new OpEntry(code, uidState.opModes.get(code), new Pair[0]));
                 }
             }
         }
@@ -1093,17 +1195,17 @@
     }
 
     private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op, long elapsedNow) {
-        if (op.running) {
-            op.continuing(elapsedNow - op.startRealtime,
-                op.uidState.state, AppOpsManager.OP_FLAG_SELF);
+        final int numFeatures = op.mFeatures.size();
+
+        for (int i = 0; i < numFeatures; i++) {
+            final FeatureOp featureOp = op.mFeatures.valueAt(i);
+            if (featureOp.running) {
+                featureOp.continuing(elapsedNow - featureOp.startRealtime,
+                        op.uidState.state, AppOpsManager.OP_FLAG_SELF);
+            }
         }
-        final OpEntry entry = new OpEntry(op.op, op.running, op.mode,
-            op.mAccessTimes != null ? op.mAccessTimes.clone() : null,
-            op.mRejectTimes != null ? op.mRejectTimes.clone() : null,
-            op.mDurations != null ? op.mDurations.clone() : null,
-            op.mProxyUids != null ? op.mProxyUids.clone() : null,
-            op.mProxyPackageNames != null ? op.mProxyPackageNames.clone() : null);
-        return entry;
+
+        return op.createEntryLocked();
     }
 
     @Override
@@ -1231,7 +1333,7 @@
             if (uidState == null) {
                 return null;
             }
-            ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState.opModes, ops);
+            ArrayList<AppOpsManager.OpEntry> resOps = collectUidOps(uidState, ops);
             if (resOps == null) {
                 return null;
             }
@@ -1244,8 +1346,11 @@
     }
 
     private void pruneOpLocked(Op op, int uid, String packageName) {
-        if (!op.hasAnyTime()) {
-            Ops ops = getOpsRawLocked(uid, packageName, false /* isPrivileged */, false /* edit */);
+        op.removeFeaturesWithNoTime();
+
+        if (op.mFeatures.size() == 0) {
+            Ops ops = getOpsRawLocked(uid, packageName, false /* isPrivileged */,
+                    false /* edit */);
             if (ops != null) {
                 ops.remove(op.op);
                 if (ops.size() <= 0) {
@@ -1398,6 +1503,12 @@
     }
 
     private void updatePermissionRevokedCompat(int uid, int switchCode, int mode) {
+        PackageManagerInternal packageManagerInternal = LocalServices.getService(
+                PackageManagerInternal.class);
+        if (packageManagerInternal.getUidTargetSdkVersion(uid) >= Build.VERSION_CODES.M) {
+            return;
+        }
+
         PackageManager packageManager = mContext.getPackageManager();
         String[] packageNames = packageManager.getPackagesForUid(uid);
         if (ArrayUtils.isEmpty(packageNames)) {
@@ -1562,9 +1673,9 @@
         if (uid != UID_ANY && callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) {
             return;
         }
-        // There are components watching for mode changes such as window manager
+        // There are features watching for mode changes such as window manager
         // and location manager which are in our process. The callbacks in these
-        // components may require permissions our remote caller does not have.
+        // features may require permissions our remote caller does not have.
         final long identity = Binder.clearCallingIdentity();
         try {
             callback.mCallback.opChanged(code, uid, packageName);
@@ -1699,7 +1810,9 @@
                                     mOpModeWatchers.get(curOp.op));
                             callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
                                     mPackageModeWatchers.get(packageName));
-                            if (!curOp.hasAnyTime()) {
+
+                            curOp.removeFeaturesWithNoTime();
+                            if (curOp.mFeatures.size() == 0) {
                                 pkgOps.removeAt(j);
                             }
                         }
@@ -1982,8 +2095,9 @@
     }
 
     @Override
-    public int noteProxyOperation(int code, int proxyUid,
-            String proxyPackageName, int proxiedUid, String proxiedPackageName) {
+    public int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
+            String proxiedFeatureId, int proxyUid, String proxyPackageName,
+            String proxyFeatureId) {
         verifyIncomingUid(proxyUid);
         verifyIncomingOp(code);
 
@@ -1998,8 +2112,8 @@
 
         final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
                 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
-        final int proxyMode = noteOperationUnchecked(code, proxyUid,
-                resolveProxyPackageName, Process.INVALID_UID, null, proxyFlags);
+        final int proxyMode = noteOperationUnchecked(code, proxyUid, resolveProxyPackageName,
+                proxyFeatureId, Process.INVALID_UID, null, null, proxyFlags);
         if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
             return proxyMode;
         }
@@ -2011,35 +2125,39 @@
         final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED
                 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
         return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
-                proxyUid, resolveProxyPackageName, proxiedFlags);
+                proxiedFeatureId, proxyUid, resolveProxyPackageName, proxyFeatureId,
+                proxiedFlags);
     }
 
     @Override
-    public int noteOperation(int code, int uid, String packageName) {
+    public int noteOperation(int code, int uid, String packageName, String featureId) {
         final CheckOpsDelegate delegate;
         synchronized (this) {
             delegate = mCheckOpsDelegate;
         }
         if (delegate == null) {
-            return noteOperationImpl(code, uid, packageName);
+            return noteOperationImpl(code, uid, packageName, featureId);
         }
-        return delegate.noteOperation(code, uid, packageName,
+        return delegate.noteOperation(code, uid, packageName, featureId,
                 AppOpsService.this::noteOperationImpl);
     }
 
-    private int noteOperationImpl(int code, int uid, String packageName) {
+    private int noteOperationImpl(int code, int uid, String packageName, String featureId) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
         String resolvedPackageName = resolvePackageName(uid, packageName);
         if (resolvedPackageName == null) {
             return AppOpsManager.MODE_IGNORED;
         }
-        return noteOperationUnchecked(code, uid, resolvedPackageName, Process.INVALID_UID, null,
-                AppOpsManager.OP_FLAG_SELF);
+        return noteOperationUnchecked(code, uid, resolvedPackageName, featureId,
+                Process.INVALID_UID, null, null, AppOpsManager.OP_FLAG_SELF);
     }
 
-    private int noteOperationUnchecked(int code, int uid, String packageName,
-            int proxyUid, String proxyPackageName, @OpFlags int flags) {
+    private int noteOperationUnchecked(int code, int uid, String packageName, String featureId,
+            int proxyUid, String proxyPackageName, @Nullable String proxyFeatureId,
+            @OpFlags int flags) {
+        // TODO moltmann: Verify that feature is declared in package
+
         boolean isPrivileged;
         try {
             isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
@@ -2058,15 +2176,18 @@
                 return AppOpsManager.MODE_ERRORED;
             }
             final Op op = getOpLocked(ops, code, true);
+            final FeatureOp featureOp = op.getOrCreateFeature(op, featureId);
             if (isOpRestrictedLocked(uid, code, packageName, isPrivileged)) {
                 scheduleOpNotedIfNeededLocked(code, uid, packageName,
                         AppOpsManager.MODE_IGNORED);
                 return AppOpsManager.MODE_IGNORED;
             }
             final UidState uidState = ops.uidState;
-            if (op.running) {
-                final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
-                    op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
+            if (featureOp.running) {
+                final OpFeatureEntry entry = getOpLocked(ops, code,
+                        false).createSingleFeatureEntryLocked(featureId).getFeatures().get(
+                        featureId);
+
                 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
                         + " code " + code + " time=" + entry.getLastAccessTime(uidState.state,
                         uidState.state, flags) + " duration=" + entry.getLastDuration(
@@ -2082,8 +2203,8 @@
                     if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + packageName);
-                    op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
-                            uidState.state, flags);
+                    featureOp.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
+                            proxyFeatureId, uidState.state, flags);
                     mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
                             uidState.state, flags);
                     scheduleOpNotedIfNeededLocked(code, uid, packageName, uidMode);
@@ -2096,8 +2217,8 @@
                     if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + packageName);
-                    op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
-                            uidState.state, flags);
+                    featureOp.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
+                            proxyFeatureId, uidState.state, flags);
                     mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
                             uidState.state, flags);
                     scheduleOpNotedIfNeededLocked(code, uid, packageName, mode);
@@ -2105,9 +2226,10 @@
                 }
             }
             if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
-                    + " package " + packageName);
-            op.accessed(System.currentTimeMillis(), proxyUid, proxyPackageName,
-                    uidState.state, flags);
+                    + " package " + packageName + (featureId == null ? "" : "." + featureId));
+            featureOp.accessed(System.currentTimeMillis(), proxyUid, proxyPackageName,
+                    proxyFeatureId, uidState.state, flags);
+            // TODO moltmann: Add features to historical app-ops
             mHistoricalRegistry.incrementOpAccessedCount(op.op, uid, packageName,
                     uidState.state, flags);
             scheduleOpNotedIfNeededLocked(code, uid, packageName,
@@ -2116,6 +2238,7 @@
         }
     }
 
+    // TODO moltmann: Allow watching for feature ops
     @Override
     public void startWatchingActive(int[] ops, IAppOpsActiveCallback callback) {
         int watchedUid = -1;
@@ -2209,7 +2332,7 @@
 
     @Override
     public void noteAsyncOp(String callingPackageName, int uid, String packageName, int opCode,
-            String message) {
+            String featureId, String message) {
         Preconditions.checkNotNull(message);
         Preconditions.checkNotNull(packageName);
         verifyAndGetIsPrivileged(uid, packageName);
@@ -2231,7 +2354,7 @@
 
                 RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key);
                 AsyncNotedAppOp asyncNotedOp = new AsyncNotedAppOp(opCode, callingUid,
-                        callingPackageName, message, now);
+                        callingPackageName, featureId, message, now);
                 final boolean[] wasNoteForwarded = {false};
 
                 if (callbacks != null) {
@@ -2242,7 +2365,7 @@
                         } catch (RemoteException e) {
                             Slog.e(TAG,
                                     "Could not forward noteOp of " + opCode + " to " + packageName
-                                            + "/" + uid, e);
+                                            + "/" + uid + "(" + featureId + ")", e);
                         }
                     });
                 }
@@ -2344,7 +2467,7 @@
 
     @Override
     public int startOperation(IBinder token, int code, int uid, String packageName,
-            boolean startIfModeDefault) {
+            String featureId, boolean startIfModeDefault) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
         String resolvedPackageName = resolvePackageName(uid, packageName);
@@ -2373,6 +2496,7 @@
             if (isOpRestrictedLocked(uid, code, resolvedPackageName, isPrivileged)) {
                 return AppOpsManager.MODE_IGNORED;
             }
+            final FeatureOp featureOp = op.getOrCreateFeature(op, featureId);
             final int switchCode = AppOpsManager.opToSwitch(code);
             final UidState uidState = ops.uidState;
             // If there is a non-default per UID policy (we set UID op mode only if
@@ -2386,8 +2510,9 @@
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + resolvedPackageName);
                     // We don't support proxy long running ops (start/stop)
-                    op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
-                            null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF);
+                    featureOp.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
+                            null /*proxyPackage*/, null, uidState.state,
+                            AppOpsManager.OP_FLAG_SELF);
                     mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
                             uidState.state, AppOpsManager.OP_FLAG_SELF);
                     return uidMode;
@@ -2401,8 +2526,9 @@
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + resolvedPackageName);
                     // We don't support proxy long running ops (start/stop)
-                    op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
-                            null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF);
+                    featureOp.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
+                            null /*proxyPackage*/, null, uidState.state,
+                            AppOpsManager.OP_FLAG_SELF);
                     mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
                             uidState.state, AppOpsManager.OP_FLAG_SELF);
                     return mode;
@@ -2410,28 +2536,30 @@
             }
             if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
                     + " package " + resolvedPackageName);
-            if (op.startNesting == 0) {
-                op.startRealtime = SystemClock.elapsedRealtime();
+            if (featureOp.startNesting == 0) {
+                featureOp.startRealtime = SystemClock.elapsedRealtime();
                 // We don't support proxy long running ops (start/stop)
-                op.started(System.currentTimeMillis(), uidState.state,
+                featureOp.started(System.currentTimeMillis(), uidState.state,
                         AppOpsManager.OP_FLAG_SELF);
                 mHistoricalRegistry.incrementOpAccessedCount(opCode, uid, packageName,
                         uidState.state, AppOpsManager.OP_FLAG_SELF);
 
-                scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true);
+                // TODO moltmann: call back when a feature became inactive
+                if (uidState.startNesting == 0) {
+                    scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true);
+                }
             }
-            op.startNesting++;
+            featureOp.startNesting++;
             uidState.startNesting++;
-            if (client.mStartedOps != null) {
-                client.mStartedOps.add(op);
-            }
+            client.mStartedOps.add(new Pair<>(op, featureId));
         }
 
         return AppOpsManager.MODE_ALLOWED;
     }
 
     @Override
-    public void finishOperation(IBinder token, int code, int uid, String packageName) {
+    public void finishOperation(IBinder token, int code, int uid, String packageName,
+            String featureId) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
         String resolvedPackageName = resolvePackageName(uid, packageName);
@@ -2456,9 +2584,16 @@
             if (op == null) {
                 return;
             }
-            if (client.mStartedOps.remove(op)) {
-                finishOperationLocked(op, /*finishNested*/ false);
-                if (op.startNesting <= 0) {
+            final FeatureOp featureOp = op.mFeatures.get(featureId);
+            if (featureOp == null) {
+                return;
+            }
+
+            if (client.mStartedOps.remove(new Pair<>(op, featureId))) {
+                finishOperationLocked(op, featureId, /*finishNested*/ false);
+
+                // TODO moltmann: call back when a feature became inactive
+                if (op.uidState.startNesting <= 0) {
                     scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, false);
                 }
 
@@ -2513,9 +2648,9 @@
 
     private void notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks,
             int code, int uid, String packageName, boolean active) {
-        // There are components watching for mode changes such as window manager
+        // There are features watching for mode changes such as window manager
         // and location manager which are in our process. The callbacks in these
-        // components may require permissions our remote caller does not have.
+        // features may require permissions our remote caller does not have.
         final long identity = Binder.clearCallingIdentity();
         try {
             final int callbackCount = callbacks.size();
@@ -2559,8 +2694,8 @@
 
     private void notifyOpChecked(ArraySet<NotedCallback> callbacks,
             int code, int uid, String packageName, int result) {
-        // There are components watching for checks in our process. The callbacks in
-        // these components may require permissions our remote caller does not have.
+        // There are features watching for checks in our process. The callbacks in
+        // these features may require permissions our remote caller does not have.
         final long identity = Binder.clearCallingIdentity();
         try {
             final int callbackCount = callbacks.size();
@@ -2604,32 +2739,34 @@
         return permInfo.getProtection() == PROTECTION_DANGEROUS;
     }
 
-    void finishOperationLocked(Op op, boolean finishNested) {
-        final int opCode = op.op;
-        final int uid = op.uidState.uid;
-        if (op.startNesting <= 1 || finishNested) {
-            if (op.startNesting == 1 || finishNested) {
+    void finishOperationLocked(@NonNull Op op, @Nullable String featureId, boolean finishNested) {
+        final FeatureOp featureOp = op.mFeatures.get(featureId);
+        final int opCode = featureOp.parent.op;
+        final int uid = featureOp.parent.uidState.uid;
+        if (featureOp.startNesting <= 1 || finishNested) {
+            if (featureOp.startNesting == 1 || finishNested) {
                 // We don't support proxy long running ops (start/stop)
-                final long duration = SystemClock.elapsedRealtime() - op.startRealtime;
-                op.finished(System.currentTimeMillis(), duration, op.uidState.state,
+                final long duration = SystemClock.elapsedRealtime() - featureOp.startRealtime;
+                featureOp.finished(System.currentTimeMillis(), duration, op.uidState.state,
                         AppOpsManager.OP_FLAG_SELF);
                 mHistoricalRegistry.increaseOpAccessDuration(opCode, uid, op.packageName,
                         op.uidState.state, AppOpsManager.OP_FLAG_SELF, duration);
             } else {
-                final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
-                    op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
+                final OpFeatureEntry entry = op.createSingleFeatureEntryLocked(
+                        featureId).getFeatures().get(featureId);
                 Slog.w(TAG, "Finishing op nesting under-run: uid " + uid + " pkg "
                         + op.packageName + " code " + opCode + " time="
                         + entry.getLastAccessTime(OP_FLAGS_ALL)
                         + " duration=" + entry.getLastDuration(MAX_PRIORITY_UID_STATE,
-                        MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL) + " nesting=" + op.startNesting);
+                        MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL) + " nesting="
+                        + featureOp.startNesting);
             }
-            if (op.startNesting >= 1) {
-                op.uidState.startNesting -= op.startNesting;
+            if (featureOp.startNesting >= 1) {
+                op.uidState.startNesting -= featureOp.startNesting;
             }
-            op.startNesting = 0;
+            featureOp.startNesting = 0;
         } else {
-            op.startNesting--;
+            featureOp.startNesting--;
             op.uidState.startNesting--;
         }
     }
@@ -3163,9 +3300,36 @@
         uidState.evalForegroundOps(mOpModeWatchers);
     }
 
+    private void readFeatureOp(XmlPullParser parser, @NonNull Op parent,
+            @Nullable String feature) throws NumberFormatException, IOException {
+        final FeatureOp featureOp = parent.getOrCreateFeature(parent, feature);
+
+        final long key = XmlUtils.readLongAttribute(parser, "n");
+
+        final int flags = AppOpsManager.extractFlagsFromKey(key);
+        final int state = AppOpsManager.extractUidStateFromKey(key);
+
+        final long accessTime = XmlUtils.readLongAttribute(parser, "t", 0);
+        final long rejectTime = XmlUtils.readLongAttribute(parser, "r", 0);
+        final long accessDuration = XmlUtils.readLongAttribute(parser, "d", 0);
+        final String proxyPkg = XmlUtils.readStringAttribute(parser, "pp");
+        final int proxyUid = XmlUtils.readIntAttribute(parser, "pu", 0);
+        final String proxyFeatureId = XmlUtils.readStringAttribute(parser, "pc");
+
+        if (accessTime > 0) {
+            featureOp.accessed(accessTime, proxyUid, proxyPkg, proxyFeatureId, state, flags);
+        }
+        if (rejectTime > 0) {
+            featureOp.rejected(rejectTime, proxyUid, proxyPkg, proxyFeatureId, state, flags);
+        }
+        if (accessDuration > 0) {
+            featureOp.running(accessTime, accessDuration, state, flags);
+        }
+    }
+
     private void readOp(XmlPullParser parser, @NonNull UidState uidState,
-            @NonNull String pkgName, boolean isPrivileged) throws NumberFormatException,
-            XmlPullParserException, IOException {
+        @NonNull String pkgName, boolean isPrivileged) throws NumberFormatException,
+        XmlPullParserException, IOException {
         Op op = new Op(uidState, pkgName,
                 Integer.parseInt(parser.getAttributeValue(null, "n")));
 
@@ -3182,26 +3346,7 @@
             }
             String tagName = parser.getName();
             if (tagName.equals("st")) {
-                final long key = XmlUtils.readLongAttribute(parser, "n");
-
-                final int flags = AppOpsManager.extractFlagsFromKey(key);
-                final int state = AppOpsManager.extractUidStateFromKey(key);
-
-                final long accessTime = XmlUtils.readLongAttribute(parser, "t", 0);
-                final long rejectTime = XmlUtils.readLongAttribute(parser, "r", 0);
-                final long accessDuration = XmlUtils.readLongAttribute(parser, "d", 0);
-                final String proxyPkg = XmlUtils.readStringAttribute(parser, "pp");
-                final int proxyUid = XmlUtils.readIntAttribute(parser, "pu", 0);
-
-                if (accessTime > 0) {
-                    op.accessed(accessTime, proxyUid, proxyPkg, state, flags);
-                }
-                if (rejectTime > 0) {
-                    op.rejected(rejectTime, proxyUid, proxyPkg, state, flags);
-                }
-                if (accessDuration > 0) {
-                    op.running(accessTime, accessDuration, state, flags);
-                }
+                readFeatureOp(parser, op, XmlUtils.readStringAttribute(parser, "id"));
             } else {
                 Slog.w(TAG, "Unknown element under <op>: "
                         + parser.getName());
@@ -3316,51 +3461,64 @@
                                 out.attribute(null, "m", Integer.toString(op.getMode()));
                             }
 
-                            final LongSparseArray keys = op.collectKeys();
-                            if (keys == null || keys.size() <= 0) {
-                                out.endTag(null, "op");
-                                continue;
-                            }
+                            for (String featureId : op.getFeatures().keySet()) {
+                                final OpFeatureEntry feature = op.getFeatures().get(
+                                        featureId);
 
-                            final int keyCount = keys.size();
-                            for (int k = 0; k < keyCount; k++) {
-                                final long key = keys.keyAt(k);
-
-                                final int uidState = AppOpsManager.extractUidStateFromKey(key);
-                                final int flags = AppOpsManager.extractFlagsFromKey(key);
-
-                                final long accessTime = op.getLastAccessTime(
-                                        uidState, uidState, flags);
-                                final long rejectTime = op.getLastRejectTime(
-                                        uidState, uidState, flags);
-                                final long accessDuration = op.getLastDuration(
-                                        uidState, uidState, flags);
-                                final String proxyPkg = op.getProxyPackageName(uidState, flags);
-                                final int proxyUid = op.getProxyUid(uidState, flags);
-
-                                if (accessTime <= 0 && rejectTime <= 0 && accessDuration <= 0
-                                        && proxyPkg == null && proxyUid < 0) {
+                                final LongSparseArray keys = feature.collectKeys();
+                                if (keys == null || keys.size() <= 0) {
                                     continue;
                                 }
+                                final int keyCount = keys.size();
 
-                                out.startTag(null, "st");
-                                out.attribute(null, "n", Long.toString(key));
-                                if (accessTime > 0) {
-                                    out.attribute(null, "t", Long.toString(accessTime));
+                                for (int k = 0; k < keyCount; k++) {
+                                    final long key = keys.keyAt(k);
+
+                                    final int uidState = AppOpsManager.extractUidStateFromKey(key);
+                                    final int flags = AppOpsManager.extractFlagsFromKey(key);
+
+                                    final long accessTime = feature.getLastAccessTime(
+                                            uidState, uidState, flags);
+                                    final long rejectTime = feature.getLastRejectTime(
+                                            uidState, uidState, flags);
+                                    final long accessDuration = feature.getLastDuration(
+                                            uidState, uidState, flags);
+                                    final String proxyPkg = feature.getProxyPackageName(uidState,
+                                            flags);
+                                    final String proxyFeatureId = feature.getProxyFeatureId(
+                                            uidState, flags);
+                                    final int proxyUid = feature.getProxyUid(uidState, flags);
+
+                                    if (accessTime <= 0 && rejectTime <= 0 && accessDuration <= 0
+                                            && proxyPkg == null && proxyUid < 0) {
+                                        continue;
+                                    }
+
+                                    out.startTag(null, "st");
+                                    if (featureId != null) {
+                                        out.attribute(null, "id", featureId);
+                                    }
+                                    out.attribute(null, "n", Long.toString(key));
+                                    if (accessTime > 0) {
+                                        out.attribute(null, "t", Long.toString(accessTime));
+                                    }
+                                    if (rejectTime > 0) {
+                                        out.attribute(null, "r", Long.toString(rejectTime));
+                                    }
+                                    if (accessDuration > 0) {
+                                        out.attribute(null, "d", Long.toString(accessDuration));
+                                    }
+                                    if (proxyPkg != null) {
+                                        out.attribute(null, "pp", proxyPkg);
+                                    }
+                                    if (proxyFeatureId != null) {
+                                        out.attribute(null, "pc", proxyFeatureId);
+                                    }
+                                    if (proxyUid >= 0) {
+                                        out.attribute(null, "pu", Integer.toString(proxyUid));
+                                    }
+                                    out.endTag(null, "st");
                                 }
-                                if (rejectTime > 0) {
-                                    out.attribute(null, "r", Long.toString(rejectTime));
-                                }
-                                if (accessDuration > 0) {
-                                    out.attribute(null, "d", Long.toString(accessDuration));
-                                }
-                                if (proxyPkg != null) {
-                                    out.attribute(null, "pp", proxyPkg);
-                                }
-                                if (proxyUid >= 0) {
-                                    out.attribute(null, "pu", Integer.toString(proxyUid));
-                                }
-                                out.endTag(null, "st");
                             }
 
                             out.endTag(null, "op");
@@ -3388,6 +3546,7 @@
 
         int userId = UserHandle.USER_SYSTEM;
         String packageName;
+        String featureId;
         String opStr;
         String modeStr;
         int op;
@@ -3492,6 +3651,8 @@
                     userId = UserHandle.parseUserArg(getNextArgRequired());
                 } else if ("--uid".equals(argument)) {
                     targetsUid = true;
+                } else if ("--feature".equals(argument)) {
+                    featureId = getNextArgRequired();
                 } else {
                     if (packageName == null) {
                         packageName = argument;
@@ -3586,13 +3747,13 @@
         pw.println("AppOps service (appops) commands:");
         pw.println("  help");
         pw.println("    Print this help text.");
-        pw.println("  start [--user <USER_ID>] <PACKAGE | UID> <OP> ");
+        pw.println("  start [--user <USER_ID>] [--feature <FEATURE_ID>] <PACKAGE | UID> <OP> ");
         pw.println("    Starts a given operation for a particular application.");
-        pw.println("  stop [--user <USER_ID>] <PACKAGE | UID> <OP> ");
+        pw.println("  stop [--user <USER_ID>] [--feature <FEATURE_ID>] <PACKAGE | UID> <OP> ");
         pw.println("    Stops a given operation for a particular application.");
         pw.println("  set [--user <USER_ID>] <[--uid] PACKAGE | UID> <OP> <MODE>");
         pw.println("    Set the mode for a particular application and operation.");
-        pw.println("  get [--user <USER_ID>] <PACKAGE | UID> [<OP>]");
+        pw.println("  get [--user <USER_ID>] [--feature <FEATURE_ID>] <PACKAGE | UID> [<OP>]");
         pw.println("    Return the mode for a particular application and optional operation.");
         pw.println("  query-op [--user <USER_ID>] <OP> [<MODE>]");
         pw.println("    Print all packages that currently have the given op in the given mode.");
@@ -3696,21 +3857,45 @@
                             pw.print(AppOpsManager.opToName(ent.getOp()));
                             pw.print(": ");
                             pw.print(AppOpsManager.modeToName(ent.getMode()));
-                            if (ent.getTime() != 0) {
-                                pw.print("; time=");
-                                TimeUtils.formatDuration(now - ent.getTime(), pw);
-                                pw.print(" ago");
-                            }
-                            if (ent.getRejectTime() != 0) {
-                                pw.print("; rejectTime=");
-                                TimeUtils.formatDuration(now - ent.getRejectTime(), pw);
-                                pw.print(" ago");
-                            }
-                            if (ent.getDuration() == -1) {
-                                pw.print(" (running)");
-                            } else if (ent.getDuration() != 0) {
-                                pw.print("; duration=");
-                                TimeUtils.formatDuration(ent.getDuration(), pw);
+                            if (shell.featureId == null) {
+                                if (ent.getTime() != 0) {
+                                    pw.print("; time=");
+                                    TimeUtils.formatDuration(now - ent.getTime(), pw);
+                                    pw.print(" ago");
+                                }
+                                if (ent.getRejectTime() != 0) {
+                                    pw.print("; rejectTime=");
+                                    TimeUtils.formatDuration(now - ent.getRejectTime(), pw);
+                                    pw.print(" ago");
+                                }
+                                if (ent.getDuration() == -1) {
+                                    pw.print(" (running)");
+                                } else if (ent.getDuration() != 0) {
+                                    pw.print("; duration=");
+                                    TimeUtils.formatDuration(ent.getDuration(), pw);
+                                }
+                            } else {
+                                final OpFeatureEntry featureEnt = ent.getFeatures().get(
+                                        shell.featureId);
+                                if (featureEnt != null) {
+                                    if (featureEnt.getTime() != 0) {
+                                        pw.print("; time=");
+                                        TimeUtils.formatDuration(now - featureEnt.getTime(), pw);
+                                        pw.print(" ago");
+                                    }
+                                    if (featureEnt.getRejectTime() != 0) {
+                                        pw.print("; rejectTime=");
+                                        TimeUtils.formatDuration(now - featureEnt.getRejectTime(),
+                                                pw);
+                                        pw.print(" ago");
+                                    }
+                                    if (featureEnt.getDuration() == -1) {
+                                        pw.print(" (running)");
+                                    } else if (featureEnt.getDuration() != 0) {
+                                        pw.print("; duration=");
+                                        TimeUtils.formatDuration(featureEnt.getDuration(), pw);
+                                    }
+                                }
                             }
                             pw.println();
                         }
@@ -3815,8 +4000,8 @@
                     }
 
                     if (shell.packageName != null) {
-                        shell.mInterface.startOperation(shell.mToken,
-                                shell.op, shell.packageUid, shell.packageName, true);
+                        shell.mInterface.startOperation(shell.mToken, shell.op, shell.packageUid,
+                                shell.packageName, shell.featureId, true);
                     } else {
                         return -1;
                     }
@@ -3830,7 +4015,7 @@
 
                     if (shell.packageName != null) {
                         shell.mInterface.finishOperation(shell.mToken,
-                                shell.op, shell.packageUid, shell.packageName);
+                                shell.op, shell.packageUid, shell.packageName, shell.featureId);
                     } else {
                         return -1;
                     }
@@ -3861,11 +4046,23 @@
         pw.println("    Output the historical data.");
     }
 
-    private void dumpStatesLocked(@NonNull PrintWriter pw, @NonNull Op op,
+    private void dumpStatesLocked(@NonNull PrintWriter pw, long nowElapsed, @NonNull Op op,
             long now, @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix) {
+        final int numFeatures = op.mFeatures.size();
+        for (int i = 0; i < numFeatures; i++) {
+            pw.print(prefix + op.mFeatures.keyAt(i) + "=[\n");
+            dumpStatesLocked(pw, nowElapsed, op, op.mFeatures.keyAt(i), now, sdf, date,
+                    prefix + "  ");
+            pw.print(prefix + "]\n");
+        }
+    }
 
-        final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
-            op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
+    private void dumpStatesLocked(@NonNull PrintWriter pw, long nowElapsed, @NonNull Op op,
+            @Nullable String featureId, long now, @NonNull SimpleDateFormat sdf,
+            @NonNull Date date, @NonNull String prefix) {
+
+        final OpFeatureEntry entry = op.createSingleFeatureEntryLocked(
+                featureId).getFeatures().get(featureId);
 
         final LongSparseArray keys = entry.collectKeys();
         if (keys == null || keys.size() <= 0) {
@@ -3886,6 +4083,7 @@
             final long accessDuration = entry.getLastDuration(
                     uidState, uidState, flags);
             final String proxyPkg = entry.getProxyPackageName(uidState, flags);
+            final String proxyFeatureId = entry.getProxyFeatureId(uidState, flags);
             final int proxyUid = entry.getProxyUid(uidState, flags);
 
             if (accessTime > 0) {
@@ -3908,6 +4106,8 @@
                     pw.print(proxyUid);
                     pw.print(", pkg=");
                     pw.print(proxyPkg);
+                    pw.print(", feature=");
+                    pw.print(proxyFeatureId);
                     pw.print("]");
                 }
                 pw.println();
@@ -3928,11 +4128,24 @@
                     pw.print(proxyUid);
                     pw.print(", pkg=");
                     pw.print(proxyPkg);
+                    pw.print(", feature=");
+                    pw.print(proxyFeatureId);
                     pw.print("]");
                 }
                 pw.println();
             }
         }
+
+        final FeatureOp featureOp = op.mFeatures.get(featureId);
+        if (featureOp.running) {
+            pw.print(prefix + "Running start at: ");
+            TimeUtils.formatDuration(nowElapsed - featureOp.startRealtime, pw);
+            pw.println();
+        }
+        if (featureOp.startNesting != 0) {
+            pw.print(prefix + "startNesting=");
+            pw.println(featureOp.startNesting);
+        }
     }
 
     @Override
@@ -4188,7 +4401,8 @@
                     if (cs.mStartedOps.size() > 0) {
                         boolean printedStarted = false;
                         for (int j=0; j<cs.mStartedOps.size(); j++) {
-                            Op op = cs.mStartedOps.get(j);
+                            final Pair<Op, String> startedOp = cs.mStartedOps.get(j);
+                            final Op op = startedOp.first;
                             if (dumpOp >= 0 && op.op != dumpOp) {
                                 continue;
                             }
@@ -4210,6 +4424,7 @@
                             }
                             pw.print("        "); pw.print("uid="); pw.print(op.uidState.uid);
                             pw.print(" pkg="); pw.print(op.packageName);
+                            pw.print(" featureId="); pw.print(startedOp.second);
                             pw.print(" op="); pw.println(AppOpsManager.opToName(op.op));
                         }
                     }
@@ -4356,16 +4571,7 @@
                             pw.print("="); pw.print(AppOpsManager.modeToName(mode));
                         }
                         pw.println("): ");
-                        dumpStatesLocked(pw, op, now, sdf, date, "          ");
-                        if (op.running) {
-                            pw.print("          Running start at: ");
-                            TimeUtils.formatDuration(nowElapsed-op.startRealtime, pw);
-                            pw.println();
-                        }
-                        if (op.startNesting != 0) {
-                            pw.print("          startNesting=");
-                            pw.println(op.startNesting);
-                        }
+                        dumpStatesLocked(pw, nowElapsed, op, now, sdf, date, "        ");
                     }
                 }
             }
@@ -4568,12 +4774,15 @@
         if (resolvedPackageName == null) {
             return false;
         }
+        // TODO moltmann: Allow to check for feature op activeness
         synchronized (AppOpsService.this) {
             for (int i = mClients.size() - 1; i >= 0; i--) {
                 final ClientState client = mClients.valueAt(i);
                 for (int j = client.mStartedOps.size() - 1; j >= 0; j--) {
-                    final Op op = client.mStartedOps.get(j);
-                    if (op.op == code && op.uidState.uid == uid) return true;
+                    final Pair<Op, String> startedOp = client.mStartedOps.get(j);
+                    if (startedOp.first.op == code && startedOp.first.uidState.uid == uid) {
+                        return true;
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/appop/TEST_MAPPING b/services/core/java/com/android/server/appop/TEST_MAPPING
index 1a5dac5..e9d2b31 100644
--- a/services/core/java/com/android/server/appop/TEST_MAPPING
+++ b/services/core/java/com/android/server/appop/TEST_MAPPING
@@ -18,6 +18,23 @@
                     "include-filter": "com.android.server.appop"
                 }
             ]
+        },
+        {
+            "name": "CtsPermissionTestCases",
+            "options": [
+                {
+                    "include-filter": "android.permission.cts.BackgroundPermissionsTest"
+                },
+                {
+                    "include-filter": "android.permission.cts.SplitPermissionTest"
+                },
+                {
+                    "include-filter": "android.permission.cts.PermissionFlagsTest"
+                },
+                {
+                    "include-filter": "android.permission.cts.SharedUidPermissionsTest"
+                }
+            ]
         }
     ]
 }
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 5fd5c4b..b3804c4 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -30,6 +30,7 @@
 import static android.net.ConnectivityManager.TETHERING_INVALID;
 import static android.net.ConnectivityManager.TETHERING_USB;
 import static android.net.ConnectivityManager.TETHERING_WIFI;
+import static android.net.ConnectivityManager.TETHERING_WIFI_P2P;
 import static android.net.ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
 import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
 import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL;
@@ -77,6 +78,9 @@
 import android.net.util.SharedLog;
 import android.net.util.VersionedBroadcastListener;
 import android.net.wifi.WifiManager;
+import android.net.wifi.p2p.WifiP2pGroup;
+import android.net.wifi.p2p.WifiP2pInfo;
+import android.net.wifi.p2p.WifiP2pManager;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -290,6 +294,7 @@
         filter.addAction(CONNECTIVITY_ACTION);
         filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+        filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
         mContext.registerReceiver(mStateReceiver, filter, null, handler);
 
         filter = new IntentFilter();
@@ -354,6 +359,8 @@
 
         if (cfg.isWifi(iface)) {
             return TETHERING_WIFI;
+        } else if (cfg.isWifiP2p(iface)) {
+            return TETHERING_WIFI_P2P;
         } else if (cfg.isUsb(iface)) {
             return TETHERING_USB;
         } else if (cfg.isBluetooth(iface)) {
@@ -527,6 +534,7 @@
 
     public void untetherAll() {
         stopTethering(TETHERING_WIFI);
+        stopTethering(TETHERING_WIFI_P2P);
         stopTethering(TETHERING_USB);
         stopTethering(TETHERING_BLUETOOTH);
     }
@@ -713,6 +721,8 @@
                 handleConnectivityAction(intent);
             } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
                 handleWifiApAction(intent);
+            } else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {
+                handleWifiP2pAction(intent);
             } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
                 mLog.log("OBSERVED configuration changed");
                 updateConfiguration();
@@ -789,6 +799,39 @@
                 }
             }
         }
+
+        private void handleWifiP2pAction(Intent intent) {
+            if (mConfig.isWifiP2pLegacyTetheringMode()) return;
+
+            final WifiP2pInfo p2pInfo =
+                    (WifiP2pInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
+            final WifiP2pGroup group =
+                    (WifiP2pGroup) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP);
+
+            if (VDBG) {
+                Log.d(TAG, "WifiP2pAction: P2pInfo: " + p2pInfo + " Group: " + group);
+            }
+
+            if (p2pInfo == null) return;
+            // When a p2p group is disconnected, p2pInfo would be cleared.
+            // group is still valid for detecting whether this device is group owner.
+            if (group == null || !group.isGroupOwner()
+                    || TextUtils.isEmpty(group.getInterface())) return;
+
+            synchronized (Tethering.this.mPublicSync) {
+                // Enter below only if this device is Group Owner with a valid interface.
+                if (p2pInfo.groupFormed) {
+                    TetherState tetherState = mTetherStates.get(group.getInterface());
+                    if (tetherState == null
+                            || (tetherState.lastState != IpServer.STATE_TETHERED
+                                && tetherState.lastState != IpServer.STATE_LOCAL_ONLY)) {
+                        enableWifiIpServingLocked(group.getInterface(), IFACE_IP_MODE_LOCAL_ONLY);
+                    }
+                } else {
+                    disableWifiP2pIpServingLocked(group.getInterface());
+                }
+            }
+        }
     }
 
     @VisibleForTesting
@@ -823,14 +866,11 @@
         }
     }
 
-    private void disableWifiIpServingLocked(String ifname, int apState) {
-        mLog.log("Canceling WiFi tethering request - AP_STATE=" + apState);
-
-        // Regardless of whether we requested this transition, the AP has gone
-        // down.  Don't try to tether again unless we're requested to do so.
-        // TODO: Remove this altogether, once Wi-Fi reliably gives us an
-        // interface name with every broadcast.
-        mWifiTetherRequested = false;
+    private void disableWifiIpServingLockedCommon(int tetheringType, String ifname, int apState) {
+        mLog.log("Canceling WiFi tethering request -"
+                + " type=" + tetheringType
+                + " interface=" + ifname
+                + " state=" + apState);
 
         if (!TextUtils.isEmpty(ifname)) {
             final TetherState ts = mTetherStates.get(ifname);
@@ -842,7 +882,7 @@
 
         for (int i = 0; i < mTetherStates.size(); i++) {
             final IpServer ipServer = mTetherStates.valueAt(i).ipServer;
-            if (ipServer.interfaceType() == TETHERING_WIFI) {
+            if (ipServer.interfaceType() == tetheringType) {
                 ipServer.unwanted();
                 return;
             }
@@ -853,6 +893,20 @@
                                            : "specified interface: " + ifname));
     }
 
+    private void disableWifiIpServingLocked(String ifname, int apState) {
+        // Regardless of whether we requested this transition, the AP has gone
+        // down.  Don't try to tether again unless we're requested to do so.
+        // TODO: Remove this altogether, once Wi-Fi reliably gives us an
+        // interface name with every broadcast.
+        mWifiTetherRequested = false;
+
+        disableWifiIpServingLockedCommon(TETHERING_WIFI, ifname, apState);
+    }
+
+    private void disableWifiP2pIpServingLocked(String ifname) {
+        disableWifiIpServingLockedCommon(TETHERING_WIFI_P2P, ifname, /* dummy */ 0);
+    }
+
     private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
         // Map wifiIpMode values to IpServer.Callback serving states, inferring
         // from mWifiTetherRequested as a final "best guess".
@@ -870,7 +924,7 @@
         }
 
         if (!TextUtils.isEmpty(ifname)) {
-            maybeTrackNewInterfaceLocked(ifname, TETHERING_WIFI);
+            maybeTrackNewInterfaceLocked(ifname);
             changeInterfaceState(ifname, ipServingMode);
         } else {
             mLog.e(String.format(
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 1907892..a1b94ca 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -28,6 +28,7 @@
 import static com.android.internal.R.array.config_tether_dhcp_range;
 import static com.android.internal.R.array.config_tether_upstream_types;
 import static com.android.internal.R.array.config_tether_usb_regexs;
+import static com.android.internal.R.array.config_tether_wifi_p2p_regexs;
 import static com.android.internal.R.array.config_tether_wifi_regexs;
 import static com.android.internal.R.bool.config_tether_upstream_automatic;
 import static com.android.internal.R.integer.config_mobile_hotspot_provision_check_period;
@@ -85,6 +86,7 @@
 
     public final String[] tetherableUsbRegexs;
     public final String[] tetherableWifiRegexs;
+    public final String[] tetherableWifiP2pRegexs;
     public final String[] tetherableBluetoothRegexs;
     public final boolean isDunRequired;
     public final boolean chooseUpstreamAutomatically;
@@ -110,6 +112,7 @@
         // us an interface name. Careful consideration needs to be given to
         // implications for Settings and for provisioning checks.
         tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs);
+        tetherableWifiP2pRegexs = getResourceStringArray(res, config_tether_wifi_p2p_regexs);
         tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs);
 
         isDunRequired = checkDunRequired(ctx, subId);
@@ -138,6 +141,15 @@
         return matchesDownstreamRegexs(iface, tetherableWifiRegexs);
     }
 
+    /** Check whether this interface is Wifi P2P interface. */
+    public boolean isWifiP2p(String iface) {
+        return matchesDownstreamRegexs(iface, tetherableWifiP2pRegexs);
+    }
+
+    public boolean isWifiP2pLegacyTetheringMode() {
+        return (tetherableWifiP2pRegexs == null || tetherableWifiP2pRegexs.length == 0);
+    }
+
     public boolean isBluetooth(String iface) {
         return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs);
     }
@@ -152,6 +164,7 @@
 
         dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs);
         dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs);
+        dumpStringArray(pw, "tetherableWifiP2pRegexs", tetherableWifiP2pRegexs);
         dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs);
 
         pw.print("isDunRequired: ");
@@ -178,6 +191,7 @@
         sj.add(String.format("subId:%d", subId));
         sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs)));
         sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs)));
+        sj.add(String.format("tetherableWifiP2pRegexs:%s", makeString(tetherableWifiP2pRegexs)));
         sj.add(String.format("tetherableBluetoothRegexs:%s",
                 makeString(tetherableBluetoothRegexs)));
         sj.add(String.format("isDunRequired:%s", isDunRequired));
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index 96ba8ef..648e07a 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -394,14 +394,10 @@
     static final String PROPERTY_PREFERRED_ADDRESS_PLAYBACK = "persist.sys.hdmi.addr.playback";
     static final String PROPERTY_PREFERRED_ADDRESS_TV = "persist.sys.hdmi.addr.tv";
 
-
     // TODO(OEM): Set this to false to keep the playback device in sleep upon hotplug event.
     //            True by default.
     static final String PROPERTY_WAKE_ON_HOTPLUG = "ro.hdmi.wake_on_hotplug";
 
-    // TODO(OEM): Set this to true to enable 'Set Menu Language' feature. False by default.
-    static final String PROPERTY_SET_MENU_LANGUAGE = "ro.hdmi.set_menu_language";
-
     /**
      * Property to save the ARC port id on system audio device.
      * <p>When ARC is initiated, this port will be used to turn on ARC.
diff --git a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
index b4c7dd3..080e6ce 100755
--- a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
+++ b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
@@ -333,7 +333,8 @@
         current.mPhysicalAddress = HdmiUtils.twoBytesToInt(params);
         current.mPortId = getPortId(current.mPhysicalAddress);
         current.mDeviceType = params[2] & 0xFF;
-        current.mDisplayName = HdmiUtils.getDefaultDeviceName(current.mDeviceType);
+        // Keep display name empty. TIF fallbacks to the service label provided by the package mg.
+        current.mDisplayName = "";
 
         // This is to manager CEC device separately in case they don't have address.
         if (mIsTvDevice) {
@@ -359,17 +360,13 @@
             return;
         }
 
-        String displayName = null;
+        String displayName = "";
         try {
-            if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT) {
-                displayName = HdmiUtils.getDefaultDeviceName(current.mLogicalAddress);
-            } else {
+            if (cmd.getOpcode() != Constants.MESSAGE_FEATURE_ABORT) {
                 displayName = new String(cmd.getParams(), "US-ASCII");
             }
         } catch (UnsupportedEncodingException e) {
             Slog.w(TAG, "Failed to decode display name: " + cmd.toString());
-            // If failed to get display name, use the default name of device.
-            displayName = HdmiUtils.getDefaultDeviceName(current.mLogicalAddress);
         }
         current.mDisplayName = displayName;
         increaseProcessedDeviceCount();
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index 61d4d4b..dde873b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -489,7 +489,7 @@
         if (oldDevice == null || oldDevice.getPhysicalAddress() != path) {
             addCecDevice(new HdmiDeviceInfo(
                     address, path, mService.pathToPortId(path), type,
-                    Constants.UNKNOWN_VENDOR_ID, HdmiUtils.getDefaultDeviceName(address)));
+                    Constants.UNKNOWN_VENDOR_ID, ""));
             // if we are adding a new device info, send out a give osd name command
             // to update the name of the device in TIF
             mService.sendCecCommand(
@@ -526,7 +526,8 @@
             return true;
         }
 
-        if (deviceInfo.getDisplayName().equals(osdName)) {
+        if (deviceInfo.getDisplayName() != null
+            && deviceInfo.getDisplayName().equals(osdName)) {
             Slog.d(TAG, "Ignore incoming <Set Osd Name> having same osd name:" + message);
             return true;
         }
@@ -1238,8 +1239,8 @@
         }
         // Wake up if the current device if ready to route.
         mService.wakeUp();
-        if (getLocalActivePort() == portId) {
-            HdmiLogger.debug("Not switching to the same port " + portId);
+        if ((getLocalActivePort() == portId) && (portId != Constants.CEC_SWITCH_ARC)) {
+            HdmiLogger.debug("Not switching to the same port " + portId + " except for arc");
             return;
         }
         // Switch to HOME if the current active port is not HOME yet
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 413e7a0..0944324 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -24,6 +24,7 @@
 import android.os.PowerManager.WakeLock;
 import android.os.SystemProperties;
 import android.provider.Settings.Global;
+import android.sysprop.HdmiProperties;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -47,7 +48,7 @@
             SystemProperties.getBoolean(Constants.PROPERTY_WAKE_ON_HOTPLUG, true);
 
     private static final boolean SET_MENU_LANGUAGE =
-            SystemProperties.getBoolean(Constants.PROPERTY_SET_MENU_LANGUAGE, false);
+            HdmiProperties.set_menu_language().orElse(false);
 
     // Used to keep the device awake while it is the active source. For devices that
     // cannot wake up via CEC commands, this address the inconvenience of having to
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index f1af73a..362955d 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -199,8 +199,7 @@
             int deviceId, int sourceMask, int sw);
     private static native boolean nativeHasKeys(long ptr,
             int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
-    private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel,
-            int displayId);
+    private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel);
     private static native void nativeRegisterInputMonitor(long ptr, InputChannel inputChannel,
             int displayId, boolean isGestureMonitor);
     private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel);
@@ -525,7 +524,6 @@
             throw new IllegalArgumentException("displayId must >= 0.");
         }
 
-
         final long ident = Binder.clearCallingIdentity();
         try {
             InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
@@ -533,7 +531,7 @@
             inputChannels[0].setToken(host.asBinder());
             nativeRegisterInputMonitor(mPtr, inputChannels[0], displayId,
                     true /*isGestureMonitor*/);
-            return new InputMonitor(inputChannelName, inputChannels[1], host);
+            return new InputMonitor(inputChannels[1], host);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -551,7 +549,7 @@
         }
         inputChannel.setToken(new Binder());
 
-        nativeRegisterInputChannel(mPtr, inputChannel, Display.INVALID_DISPLAY);
+        nativeRegisterInputChannel(mPtr, inputChannel);
     }
 
     /**
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index b7fcd3f..471fa72 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -3570,10 +3570,14 @@
                 return;
             }
             if (!setVisible) {
-                // Client hides the IME directly.
-                if (mCurClient != null && mCurClient.client != null) {
-                    executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
-                            MSG_APPLY_IME_VISIBILITY, setVisible ? 1 : 0, mCurClient));
+                if (mCurClient != null) {
+                    // IMMS only knows of focused window, not the actual IME target.
+                    // e.g. it isn't aware of any window that has both
+                    // NOT_FOCUSABLE, ALT_FOCUSABLE_IM flags set and can the IME target.
+                    // Send it to window manager to hide IME from IME target window.
+                    // TODO(b/139861270): send to mCurClient.client once IMMS is aware of
+                    // actual IME target.
+                    mWindowManagerInternal.hideIme(mCurClient.selfReportedDisplayId);
                 }
             } else {
                 // Send to window manager to show IME after IME layout finishes.
@@ -4208,7 +4212,7 @@
             // with other IME windows based on type vs. grouping based on whichever token happens
             // to get selected by the system later on.
             attrs.token = mSwitchingDialogToken;
-            attrs.privateFlags |= LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+            attrs.privateFlags |= LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
             attrs.setTitle("Select input method");
             w.setAttributes(attrs);
             updateSystemUiLocked(mImeWindowVis, mBackDisposition);
diff --git a/services/core/java/com/android/server/location/CallerIdentity.java b/services/core/java/com/android/server/location/CallerIdentity.java
index da31d0b..61e5d1f 100644
--- a/services/core/java/com/android/server/location/CallerIdentity.java
+++ b/services/core/java/com/android/server/location/CallerIdentity.java
@@ -16,6 +16,8 @@
 
 package com.android.server.location;
 
+import android.annotation.NonNull;
+
 /**
  * Represents the calling process's uid, pid, and package name.
  */
@@ -23,10 +25,13 @@
     public final int mUid;
     public final int mPid;
     public final String mPackageName;
+    public final @NonNull String mListenerIdentifier;
 
-    public CallerIdentity(int uid, int pid, String packageName) {
+    public CallerIdentity(int uid, int pid, String packageName,
+            @NonNull String listenerIdentifier) {
         mUid = uid;
         mPid = pid;
         mPackageName = packageName;
+        mListenerIdentifier = listenerIdentifier;
     }
 }
diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java
index a192206..4f10a71 100644
--- a/services/core/java/com/android/server/location/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/GeofenceManager.java
@@ -16,6 +16,7 @@
 
 package com.android.server.location;
 
+import android.annotation.NonNull;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
 import android.content.ContentResolver;
@@ -151,14 +152,16 @@
     }
 
     public void addFence(LocationRequest request, Geofence geofence, PendingIntent intent,
-            int allowedResolutionLevel, int uid, String packageName) {
+            int allowedResolutionLevel, int uid, String packageName,
+            @NonNull String listenerIdentifier) {
         if (D) {
             Slog.d(TAG, "addFence: request=" + request + ", geofence=" + geofence
                     + ", intent=" + intent + ", uid=" + uid + ", packageName=" + packageName);
         }
 
         GeofenceState state = new GeofenceState(geofence,
-                request.getExpireAt(), allowedResolutionLevel, uid, packageName, intent);
+                request.getExpireAt(), allowedResolutionLevel, uid, packageName, listenerIdentifier,
+                intent);
         synchronized (mLock) {
             // first make sure it doesn't already exist
             for (int i = mFences.size() - 1; i >= 0; i--) {
@@ -301,7 +304,8 @@
                 int op = LocationManagerService.resolutionLevelToOp(state.mAllowedResolutionLevel);
                 if (op >= 0) {
                     if (mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, state.mUid,
-                            state.mPackageName) != AppOpsManager.MODE_ALLOWED) {
+                            state.mPackageName, null, state.mListenerIdentifier)
+                            != AppOpsManager.MODE_ALLOWED) {
                         if (D) {
                             Slog.d(TAG, "skipping geofence processing for no op app: "
                                     + state.mPackageName);
diff --git a/services/core/java/com/android/server/location/GeofenceState.java b/services/core/java/com/android/server/location/GeofenceState.java
index 3ebe20a..fe0719d 100644
--- a/services/core/java/com/android/server/location/GeofenceState.java
+++ b/services/core/java/com/android/server/location/GeofenceState.java
@@ -17,6 +17,7 @@
 
 package com.android.server.location;
 
+import android.annotation.NonNull;
 import android.app.PendingIntent;
 import android.location.Geofence;
 import android.location.Location;
@@ -38,13 +39,14 @@
     public final int mAllowedResolutionLevel;
     public final int mUid;
     public final String mPackageName;
+    public final @NonNull String mListenerIdentifier;
     public final PendingIntent mIntent;
 
     int mState;  // current state
     double mDistanceToCenter;  // current distance to center of fence
 
-    public GeofenceState(Geofence fence, long expireAt,
-            int allowedResolutionLevel, int uid, String packageName, PendingIntent intent) {
+    public GeofenceState(Geofence fence, long expireAt, int allowedResolutionLevel, int uid,
+            String packageName, @NonNull String listenerIdentifier, PendingIntent intent) {
         mState = STATE_UNKNOWN;
         mDistanceToCenter = Double.MAX_VALUE;
 
@@ -53,6 +55,7 @@
         mAllowedResolutionLevel = allowedResolutionLevel;
         mUid = uid;
         mPackageName = packageName;
+        mListenerIdentifier = listenerIdentifier;
         mIntent = intent;
 
         mLocation = new Location("");
diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java
index aa8a25a..25b544f 100644
--- a/services/core/java/com/android/server/location/RemoteListenerHelper.java
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -182,7 +182,9 @@
         }
 
         return mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, callerIdentity.mUid,
-                callerIdentity.mPackageName) == AppOpsManager.MODE_ALLOWED;
+                callerIdentity.mPackageName, null,
+                "Location sent to " + callerIdentity.mListenerIdentifier)
+                == AppOpsManager.MODE_ALLOWED;
     }
 
     protected void logPermissionDisabledEventNotReported(String tag, String packageName,
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index bad484f..34fb641 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -118,6 +118,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockPatternUtils.CredentialType;
 import com.android.internal.widget.LockSettingsInternal;
+import com.android.internal.widget.LockscreenCredential;
 import com.android.internal.widget.VerifyCredentialResponse;
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
@@ -2058,7 +2059,8 @@
             @UserIdInt int userHandle) {
         synchronized (this) {
             mUserPasswordMetrics.put(userHandle,
-                    PasswordMetrics.computeForCredential(credentialType, password));
+                    PasswordMetrics.computeForCredential(
+                            LockscreenCredential.createRaw(credentialType, password)));
         }
     }
 
@@ -2069,7 +2071,7 @@
             // since the user never unlock the device manually. In this case, always
             // return a default metrics object. This is to distinguish this case from
             // the case where during boot user password is unknown yet (returning null here)
-            return new PasswordMetrics();
+            return new PasswordMetrics(CREDENTIAL_TYPE_NONE);
         }
         synchronized (this) {
             return mUserPasswordMetrics.get(userHandle);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
index a5d59e3..0a8e5bd 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
@@ -16,16 +16,12 @@
 
 package com.android.server.locksettings;
 
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
-
-import static com.android.internal.widget.LockPatternUtils.stringToPattern;
-
 import android.app.ActivityManager;
 import android.os.ShellCommand;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
+import com.android.internal.widget.LockscreenCredential;
 
 import java.io.PrintWriter;
 
@@ -189,31 +185,49 @@
                 mLockPatternUtils.isSyntheticPasswordEnabled()));
     }
 
+    private LockscreenCredential getOldCredential() {
+        if (mLockPatternUtils.isLockPasswordEnabled(mCurrentUserId)) {
+            final int quality = mLockPatternUtils.getKeyguardStoredPasswordQuality(mCurrentUserId);
+            if (LockPatternUtils.isQualityAlphabeticPassword(quality)) {
+                return LockscreenCredential.createPassword(mOld);
+            } else {
+                return LockscreenCredential.createPin(mOld);
+            }
+        } else if (mLockPatternUtils.isLockPatternEnabled(mCurrentUserId)) {
+            return LockscreenCredential.createPattern(LockPatternUtils.byteArrayToPattern(
+                    mOld.getBytes()));
+        } else {
+            return LockscreenCredential.createNone();
+        }
+    }
+
     private void runSetPattern() {
-        byte[] oldBytes = mOld != null ? mOld.getBytes() : null;
-        mLockPatternUtils.saveLockPattern(stringToPattern(mNew), oldBytes, mCurrentUserId);
+        mLockPatternUtils.setLockCredential(
+                LockscreenCredential.createPattern(LockPatternUtils.byteArrayToPattern(
+                        mNew.getBytes())),
+                getOldCredential(),
+                mCurrentUserId);
         getOutPrintWriter().println("Pattern set to '" + mNew + "'");
     }
 
     private void runSetPassword() {
-        byte[] newBytes = mNew != null ? mNew.getBytes() : null;
-        byte[] oldBytes = mOld != null ? mOld.getBytes() : null;
-        mLockPatternUtils.saveLockPassword(newBytes, oldBytes, PASSWORD_QUALITY_ALPHABETIC,
+        mLockPatternUtils.setLockCredential(LockscreenCredential.createPassword(mNew),
+                getOldCredential(),
                 mCurrentUserId);
         getOutPrintWriter().println("Password set to '" + mNew + "'");
     }
 
     private void runSetPin() {
-        byte[] newBytes = mNew != null ? mNew.getBytes() : null;
-        byte[] oldBytes = mOld != null ? mOld.getBytes() : null;
-        mLockPatternUtils.saveLockPassword(newBytes, oldBytes, PASSWORD_QUALITY_NUMERIC,
+        mLockPatternUtils.setLockCredential(LockscreenCredential.createPin(mNew),
+                getOldCredential(),
                 mCurrentUserId);
         getOutPrintWriter().println("Pin set to '" + mNew + "'");
     }
 
     private void runClear() {
-        byte[] oldBytes = mOld != null ? mOld.getBytes() : null;
-        mLockPatternUtils.clearLock(oldBytes, mCurrentUserId);
+        mLockPatternUtils.setLockCredential(LockscreenCredential.createNone(),
+                getOldCredential(),
+                mCurrentUserId);
         getOutPrintWriter().println("Lock credential cleared");
     }
 
@@ -238,13 +252,8 @@
             }
 
             try {
-                final boolean result;
-                if (havePassword) {
-                    byte[] passwordBytes = mOld != null ? mOld.getBytes() : null;
-                    result = mLockPatternUtils.checkPassword(passwordBytes, mCurrentUserId);
-                } else {
-                    result = mLockPatternUtils.checkPattern(stringToPattern(mOld), mCurrentUserId);
-                }
+                final boolean result = mLockPatternUtils.checkCredential(getOldCredential(),
+                        mCurrentUserId, null);
                 if (!result) {
                     if (!mLockPatternUtils.isManagedProfileWithUnifiedChallenge(mCurrentUserId)) {
                         mLockPatternUtils.reportFailedPasswordAttempt(mCurrentUserId);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index 5594614..f4cad63 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -95,8 +95,6 @@
 
     @VisibleForTesting
     public static class CredentialHash {
-        /** Deprecated private static final int VERSION_LEGACY = 0; */
-        private static final int VERSION_GATEKEEPER = 1;
 
         private CredentialHash(byte[] hash, @CredentialType int type) {
             if (type != LockPatternUtils.CREDENTIAL_TYPE_NONE) {
@@ -126,42 +124,6 @@
 
         byte[] hash;
         @CredentialType int type;
-
-        public byte[] toBytes() {
-            try {
-                ByteArrayOutputStream os = new ByteArrayOutputStream();
-                DataOutputStream dos = new DataOutputStream(os);
-                dos.write(VERSION_GATEKEEPER);
-                dos.write(type);
-                if (hash != null && hash.length > 0) {
-                    dos.writeInt(hash.length);
-                    dos.write(hash);
-                } else {
-                    dos.writeInt(0);
-                }
-                dos.close();
-                return os.toByteArray();
-            } catch (IOException e) {
-                throw new IllegalStateException("Fail to serialze credential hash", e);
-            }
-        }
-
-        public static CredentialHash fromBytes(byte[] bytes) {
-            try {
-                DataInputStream is = new DataInputStream(new ByteArrayInputStream(bytes));
-                /* int version = */ is.read();
-                int type = is.read();
-                int hashSize = is.readInt();
-                byte[] hash = null;
-                if (hashSize > 0) {
-                    hash = new byte[hashSize];
-                    is.readFully(hash);
-                }
-                return new CredentialHash(hash, type);
-            } catch (IOException e) {
-                throw new IllegalStateException("Fail to deserialze credential hash", e);
-            }
-        }
     }
 
     public LockSettingsStorage(Context context) {
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index e753a7b..4816ceb 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -43,7 +43,7 @@
  * Maintains a connection to a particular media route provider service.
  */
 final class MediaRoute2ProviderProxy implements ServiceConnection {
-    private static final String TAG = "MediaRoute2Provider";
+    private static final String TAG = "MR2ProviderProxy";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final Context mContext;
@@ -93,7 +93,7 @@
 
     public void unselectRoute(String packageName, String routeId) {
         if (mConnectionReady) {
-            mActiveConnection.unselectRotue(packageName, routeId);
+            mActiveConnection.unselectRoute(packageName, routeId);
             updateBinding();
         }
     }
@@ -105,6 +105,20 @@
         }
     }
 
+    public void requestSetVolume(MediaRoute2Info route, int volume) {
+        if (mConnectionReady) {
+            mActiveConnection.requestSetVolume(route.getId(), volume);
+            updateBinding();
+        }
+    }
+
+    public void requestUpdateVolume(MediaRoute2Info route, int delta) {
+        if (mConnectionReady) {
+            mActiveConnection.requestUpdateVolume(route.getId(), delta);
+            updateBinding();
+        }
+    }
+
     @Nullable
     public MediaRoute2ProviderInfo getProviderInfo() {
         return mProviderInfo;
@@ -260,7 +274,9 @@
                 .setUniqueId(mUniqueId)
                 .build();
         }
-        mHandler.post(mStateChanged);
+        if (mCallback != null) {
+            mCallback.onProviderStateChanged(MediaRoute2ProviderProxy.this);
+        }
     }
 
     private void disconnect() {
@@ -277,15 +293,6 @@
         return "Service connection " + mComponentName.flattenToShortString();
     }
 
-    private final Runnable mStateChanged = new Runnable() {
-        @Override
-        public void run() {
-            if (mCallback != null) {
-                mCallback.onProviderStateChanged(MediaRoute2ProviderProxy.this);
-            }
-        }
-    };
-
     public interface Callback {
         void onProviderStateChanged(MediaRoute2ProviderProxy provider);
     }
@@ -324,7 +331,7 @@
             }
         }
 
-        public void unselectRotue(String packageName, String routeId) {
+        public void unselectRoute(String packageName, String routeId) {
             try {
                 mProvider.unselectRoute(packageName, routeId);
             } catch (RemoteException ex) {
@@ -340,6 +347,22 @@
             }
         }
 
+        public void requestSetVolume(String routeId, int volume) {
+            try {
+                mProvider.requestSetVolume(routeId, volume);
+            } catch (RemoteException ex) {
+                Slog.e(TAG, "Failed to deliver request to request set volume.", ex);
+            }
+        }
+
+        public void requestUpdateVolume(String routeId, int delta) {
+            try {
+                mProvider.requestUpdateVolume(routeId, delta);
+            } catch (RemoteException ex) {
+                Slog.e(TAG, "Failed to deliver request to request update volume.", ex);
+            }
+        }
+
         @Override
         public void binderDied() {
             mHandler.post(() -> onConnectionDied(Connection.this));
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java b/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java
index 194015d..c95119d 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java
@@ -35,9 +35,10 @@
 import java.util.Collections;
 
 /**
+ * Watches changes of packages, or scan them for finding media route providers.
  */
 final class MediaRoute2ProviderWatcher {
-    private static final String TAG = "MediaRouteProvider";  // max. 23 chars
+    private static final String TAG = "MR2ProviderWatcher";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final Context mContext;
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 668f2be..361dc36 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -55,7 +55,7 @@
  * TODO: Merge this to MediaRouterService once it's finished.
  */
 class MediaRouter2ServiceImpl {
-    private static final String TAG = "MediaRouter2ServiceImpl";
+    private static final String TAG = "MR2ServiceImpl";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final Context mContext;
@@ -198,6 +198,34 @@
         }
     }
 
+    public void requestSetVolume2(IMediaRouter2Client client, MediaRoute2Info route, int volume) {
+        Objects.requireNonNull(client, "client must not be null");
+        Objects.requireNonNull(route, "route must not be null");
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                requestSetVolumeLocked(client, route, volume);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    public void requestUpdateVolume2(IMediaRouter2Client client, MediaRoute2Info route, int delta) {
+        Objects.requireNonNull(client, "client must not be null");
+        Objects.requireNonNull(route, "route must not be null");
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                requestUpdateVolumeLocked(client, route, delta);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     public void selectClientRoute2(@NonNull IMediaRouter2Manager manager,
             String packageName, @Nullable MediaRoute2Info route) {
         final long token = Binder.clearCallingIdentity();
@@ -210,6 +238,37 @@
         }
     }
 
+    public void requestSetVolume2Manager(IMediaRouter2Manager manager,
+            MediaRoute2Info route, int volume) {
+        Objects.requireNonNull(manager, "manager must not be null");
+        Objects.requireNonNull(route, "route must not be null");
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                requestSetVolumeLocked(manager, route, volume);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    public void requestUpdateVolume2Manager(IMediaRouter2Manager manager,
+            MediaRoute2Info route, int delta) {
+        Objects.requireNonNull(manager, "manager must not be null");
+        Objects.requireNonNull(route, "route must not be null");
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                requestUpdateVolumeLocked(manager, route, delta);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+
     public void registerClient(@NonNull IMediaRouterClient client, @NonNull String packageName) {
         Objects.requireNonNull(client, "client must not be null");
 
@@ -280,11 +339,11 @@
             int uid, int pid, String packageName, int userId, boolean trusted) {
         final IBinder binder = client.asBinder();
         if (mAllClientRecords.get(binder) == null) {
-            boolean newUser = false;
             UserRecord userRecord = mUserRecords.get(userId);
             if (userRecord == null) {
                 userRecord = new UserRecord(userId);
-                newUser = true;
+                mUserRecords.put(userId, userRecord);
+                initializeUserLocked(userRecord);
             }
             Client2Record clientRecord = new Client2Record(userRecord, client, uid, pid,
                     packageName, trusted);
@@ -294,11 +353,6 @@
                 throw new RuntimeException("Media router client died prematurely.", ex);
             }
 
-            if (newUser) {
-                mUserRecords.put(userId, userRecord);
-                initializeUserLocked(userRecord);
-            }
-
             userRecord.mClientRecords.add(clientRecord);
             mAllClientRecords.put(binder, clientRecord);
 
@@ -362,6 +416,30 @@
         }
     }
 
+    private void requestSetVolumeLocked(IMediaRouter2Client client, MediaRoute2Info route,
+            int volume) {
+        final IBinder binder = client.asBinder();
+        ClientRecord clientRecord = mAllClientRecords.get(binder);
+
+        if (clientRecord != null) {
+            clientRecord.mUserRecord.mHandler.sendMessage(
+                    obtainMessage(UserHandler::requestSetVolume,
+                            clientRecord.mUserRecord.mHandler, route, volume));
+        }
+    }
+
+    private void requestUpdateVolumeLocked(IMediaRouter2Client client, MediaRoute2Info route,
+            int delta) {
+        final IBinder binder = client.asBinder();
+        ClientRecord clientRecord = mAllClientRecords.get(binder);
+
+        if (clientRecord != null) {
+            clientRecord.mUserRecord.mHandler.sendMessage(
+                    obtainMessage(UserHandler::requestUpdateVolume,
+                            clientRecord.mUserRecord.mHandler, route, delta));
+        }
+    }
+
     private void registerManagerLocked(IMediaRouter2Manager manager,
             int uid, int pid, String packageName, int userId, boolean trusted) {
         final IBinder binder = manager.asBinder();
@@ -424,6 +502,31 @@
         }
     }
 
+    private void requestSetVolumeLocked(IMediaRouter2Manager manager, MediaRoute2Info route,
+            int volume) {
+        final IBinder binder = manager.asBinder();
+        ManagerRecord managerRecord = mAllManagerRecords.get(binder);
+
+        if (managerRecord != null) {
+            managerRecord.mUserRecord.mHandler.sendMessage(
+                    obtainMessage(UserHandler::requestSetVolume,
+                            managerRecord.mUserRecord.mHandler, route, volume));
+        }
+    }
+
+    private void requestUpdateVolumeLocked(IMediaRouter2Manager manager, MediaRoute2Info route,
+            int delta) {
+        final IBinder binder = manager.asBinder();
+        ManagerRecord managerRecord = mAllManagerRecords.get(binder);
+
+        if (managerRecord != null) {
+            managerRecord.mUserRecord.mHandler.sendMessage(
+                    obtainMessage(UserHandler::requestUpdateVolume,
+                            managerRecord.mUserRecord.mHandler, route, delta));
+        }
+    }
+
+
     private void initializeUserLocked(UserRecord userRecord) {
         if (DEBUG) {
             Slog.d(TAG, userRecord + ": Initialized");
@@ -679,6 +782,20 @@
             }
         }
 
+        private void requestSetVolume(MediaRoute2Info route, int volume) {
+            final MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
+            if (provider != null) {
+                provider.requestSetVolume(route, volume);
+            }
+        }
+
+        private void requestUpdateVolume(MediaRoute2Info route, int delta) {
+            final MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
+            if (provider != null) {
+                provider.requestUpdateVolume(route, delta);
+            }
+        }
+
         private void scheduleUpdateProviderInfos() {
             if (!mProviderInfosUpdateScheduled) {
                 mProviderInfosUpdateScheduled = true;
@@ -693,8 +810,6 @@
             if (service == null) {
                 return;
             }
-            final List<IMediaRouter2Manager> managers = new ArrayList<>();
-            final List<IMediaRouter2Client> clients = new ArrayList<>();
             final List<MediaRoute2ProviderInfo> providers = new ArrayList<>();
             for (MediaRoute2ProviderProxy mediaProvider : mMediaProviders) {
                 final MediaRoute2ProviderInfo providerInfo =
@@ -707,6 +822,8 @@
             }
             mProviderInfos = providers;
 
+            final List<IMediaRouter2Manager> managers = new ArrayList<>();
+            final List<IMediaRouter2Client> clients = new ArrayList<>();
             synchronized (service.mLock) {
                 for (ManagerRecord managerRecord : mUserRecord.mManagerRecords) {
                     managers.add(managerRecord.mManager);
@@ -756,9 +873,8 @@
             }
             List<IMediaRouter2Manager> managers = new ArrayList<>();
             synchronized (service.mLock) {
-                final int count = mUserRecord.mManagerRecords.size();
-                for (int i = 0; i < count; i++) {
-                    managers.add(mUserRecord.mManagerRecords.get(i).mManager);
+                for (ManagerRecord managerRecord : mUserRecord.mManagerRecords) {
+                    managers.add(managerRecord.mManager);
                 }
             }
             for (IMediaRouter2Manager manager : managers) {
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 796a25d..afd92f6 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -499,6 +499,32 @@
         mService2.setControlCategories2(client, categories);
     }
 
+    // Binder call
+    @Override
+    public void requestSetVolume2(IMediaRouter2Client client, MediaRoute2Info route, int volume) {
+        mService2.requestSetVolume2(client, route, volume);
+    }
+
+    // Binder call
+    @Override
+    public void requestUpdateVolume2(IMediaRouter2Client client, MediaRoute2Info route, int delta) {
+        mService2.requestUpdateVolume2(client, route, delta);
+    }
+
+    // Binder call
+    @Override
+    public void requestSetVolume2Manager(IMediaRouter2Manager manager,
+            MediaRoute2Info route, int volume) {
+        mService2.requestSetVolume2Manager(manager, route, volume);
+    }
+
+    // Binder call
+    @Override
+    public void requestUpdateVolume2Manager(IMediaRouter2Manager manager,
+            MediaRoute2Info route, int delta) {
+        mService2.requestUpdateVolume2Manager(manager, route, delta);
+    }
+
     void restoreBluetoothA2dp() {
         try {
             boolean a2dpOn;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 976a0c6..09be474 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -217,7 +217,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.os.SomeArgs;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.ConcurrentUtils;
@@ -385,6 +384,7 @@
     private static final int MSG_SUBSCRIPTION_OVERRIDE = 16;
     private static final int MSG_METERED_RESTRICTED_PACKAGES_CHANGED = 17;
     private static final int MSG_SET_NETWORK_TEMPLATE_ENABLED = 18;
+    private static final int MSG_SUBSCRIPTION_PLANS_CHANGED = 19;
 
     private static final int UID_MSG_STATE_CHANGED = 100;
     private static final int UID_MSG_GONE = 101;
@@ -797,6 +797,7 @@
                         writePolicyAL();
                     }
 
+                    enableFirewallChainUL(FIREWALL_CHAIN_STANDBY, true);
                     setRestrictBackgroundUL(mLoadedRestrictBackground);
                     updateRulesForGlobalChangeAL(false);
                     updateNotificationsNL();
@@ -1509,6 +1510,11 @@
         latch.await(5, TimeUnit.SECONDS);
     }
 
+    @VisibleForTesting
+    Handler getHandlerForTesting() {
+        return mHandler;
+    }
+
     /**
      * Update mobile policies with data cycle information from {@link CarrierConfigManager}
      * if necessary.
@@ -3064,6 +3070,34 @@
         mContext.enforceCallingOrSelfPermission(MANAGE_SUBSCRIPTION_PLANS, TAG);
     }
 
+    private void enforceSubscriptionPlanValidity(SubscriptionPlan[] plans) {
+        // nothing to check if no plans
+        if (plans.length == 0) {
+            return;
+        }
+
+        long applicableNetworkTypes = 0;
+        boolean allNetworks = false;
+        for (SubscriptionPlan plan : plans) {
+            if (plan.getNetworkTypes() == null) {
+                allNetworks = true;
+            } else {
+                if ((applicableNetworkTypes & plan.getNetworkTypesBitMask()) != 0) {
+                    throw new IllegalArgumentException(
+                            "Multiple subscription plans defined for a single network type.");
+                } else {
+                    applicableNetworkTypes |= plan.getNetworkTypesBitMask();
+                }
+            }
+        }
+
+        // ensure at least one plan applies for every network type
+        if (!allNetworks) {
+            throw new IllegalArgumentException(
+                    "No generic subscription plan that applies to all network types.");
+        }
+    }
+
     @Override
     public SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage) {
         enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
@@ -3228,6 +3262,7 @@
     @Override
     public void setSubscriptionPlans(int subId, SubscriptionPlan[] plans, String callingPackage) {
         enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
+        enforceSubscriptionPlanValidity(plans);
 
         for (SubscriptionPlan plan : plans) {
             Preconditions.checkNotNull(plan);
@@ -3256,6 +3291,8 @@
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
             intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
             mContext.sendBroadcast(intent, android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS);
+            mHandler.sendMessage(
+                    mHandler.obtainMessage(MSG_SUBSCRIPTION_PLANS_CHANGED, subId, 0, plans));
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -3282,7 +3319,7 @@
 
     @Override
     public void setSubscriptionOverride(int subId, int overrideMask, int overrideValue,
-            long networkTypeMask, long timeoutMillis, String callingPackage) {
+            long timeoutMillis, String callingPackage) {
         enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
 
         // We can only override when carrier told us about plans
@@ -3300,16 +3337,11 @@
         final boolean overrideEnabled = Settings.Global.getInt(mContext.getContentResolver(),
                 NETPOLICY_OVERRIDE_ENABLED, 1) != 0;
         if (overrideEnabled || overrideValue == 0) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = subId;
-            args.arg2 = overrideMask;
-            args.arg3 = overrideValue;
-            args.arg4 = networkTypeMask;
-            mHandler.sendMessage(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, args));
+            mHandler.sendMessage(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE,
+                    overrideMask, overrideValue, subId));
             if (timeoutMillis > 0) {
-                args.arg3 = 0;
-                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, args),
-                        timeoutMillis);
+                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE,
+                        overrideMask, 0, subId), timeoutMillis);
             }
         }
     }
@@ -3799,39 +3831,6 @@
     }
 
     /**
-     * Toggle the firewall standby chain and inform listeners if the uid rules have effectively
-     * changed.
-     */
-    @GuardedBy("mUidRulesFirstLock")
-    void updateRulesForAppIdleParoleUL() {
-        boolean paroled = mUsageStats.isAppIdleParoleOn();
-        boolean enableChain = !paroled;
-        enableFirewallChainUL(FIREWALL_CHAIN_STANDBY, enableChain);
-
-        int ruleCount = mUidFirewallStandbyRules.size();
-        for (int i = 0; i < ruleCount; i++) {
-            int uid = mUidFirewallStandbyRules.keyAt(i);
-            int oldRules = mUidRules.get(uid);
-            if (enableChain) {
-                // Chain wasn't enabled before and the other power-related
-                // chains are whitelists, so we can clear the
-                // MASK_ALL_NETWORKS part of the rules and re-inform listeners if
-                // the effective rules result in blocking network access.
-                oldRules &= MASK_METERED_NETWORKS;
-            } else {
-                // Skip if it had no restrictions to begin with
-                if ((oldRules & MASK_ALL_NETWORKS) == 0) continue;
-            }
-            final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldRules, paroled);
-            if (newUidRules == RULE_NONE) {
-                mUidRules.delete(uid);
-            } else {
-                mUidRules.put(uid, newUidRules);
-            }
-        }
-    }
-
-    /**
      * Update rules that might be changed by {@link #mRestrictBackground},
      * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
      */
@@ -4286,7 +4285,7 @@
     private void updateRulesForPowerRestrictionsUL(int uid) {
         final int oldUidRules = mUidRules.get(uid, RULE_NONE);
 
-        final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldUidRules, false);
+        final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldUidRules);
 
         if (newUidRules == RULE_NONE) {
             mUidRules.delete(uid);
@@ -4300,30 +4299,28 @@
      *
      * @param uid the uid of the app to update rules for
      * @param oldUidRules the current rules for the uid, in order to determine if there's a change
-     * @param paroled whether to ignore idle state of apps and only look at other restrictions.
      *
      * @return the new computed rules for the uid
      */
-    private int updateRulesForPowerRestrictionsUL(int uid, int oldUidRules, boolean paroled) {
+    private int updateRulesForPowerRestrictionsUL(int uid, int oldUidRules) {
         if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
             Trace.traceBegin(Trace.TRACE_TAG_NETWORK,
-                    "updateRulesForPowerRestrictionsUL: " + uid + "/" + oldUidRules + "/"
-                    + (paroled ? "P" : "-"));
+                    "updateRulesForPowerRestrictionsUL: " + uid + "/" + oldUidRules);
         }
         try {
-            return updateRulesForPowerRestrictionsULInner(uid, oldUidRules, paroled);
+            return updateRulesForPowerRestrictionsULInner(uid, oldUidRules);
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
         }
     }
 
-    private int updateRulesForPowerRestrictionsULInner(int uid, int oldUidRules, boolean paroled) {
+    private int updateRulesForPowerRestrictionsULInner(int uid, int oldUidRules) {
         if (!isUidValidForBlacklistRules(uid)) {
             if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid);
             return RULE_NONE;
         }
 
-        final boolean isIdle = !paroled && isUidIdle(uid);
+        final boolean isIdle = isUidIdle(uid);
         final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode;
         final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
 
@@ -4395,14 +4392,6 @@
             } catch (NameNotFoundException nnfe) {
             }
         }
-
-        @Override
-        public void onParoleStateChanged(boolean isParoleOn) {
-            synchronized (mUidRulesFirstLock) {
-                mLogger.paroleStateChanged(isParoleOn);
-                updateRulesForAppIdleParoleUL();
-            }
-        }
     }
 
     private void dispatchUidRulesChanged(INetworkPolicyListener listener, int uid, int uidRules) {
@@ -4445,11 +4434,20 @@
     }
 
     private void dispatchSubscriptionOverride(INetworkPolicyListener listener, int subId,
-            int overrideMask, int overrideValue, long networkTypeMask) {
+            int overrideMask, int overrideValue) {
         if (listener != null) {
             try {
-                listener.onSubscriptionOverride(subId, overrideMask, overrideValue,
-                        networkTypeMask);
+                listener.onSubscriptionOverride(subId, overrideMask, overrideValue);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    private void dispatchSubscriptionPlansChanged(INetworkPolicyListener listener, int subId,
+            SubscriptionPlan[] plans) {
+        if (listener != null) {
+            try {
+                listener.onSubscriptionPlansChanged(subId, plans);
             } catch (RemoteException ignored) {
             }
         }
@@ -4550,16 +4548,13 @@
                     return true;
                 }
                 case MSG_SUBSCRIPTION_OVERRIDE: {
-                    final SomeArgs args = (SomeArgs) msg.obj;
-                    final int subId = (int) args.arg1;
-                    final int overrideMask = (int) args.arg2;
-                    final int overrideValue = (int) args.arg3;
-                    final long networkTypeMask = (long) args.arg4;
+                    final int overrideMask = msg.arg1;
+                    final int overrideValue = msg.arg2;
+                    final int subId = (int) msg.obj;
                     final int length = mListeners.beginBroadcast();
                     for (int i = 0; i < length; i++) {
                         final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
-                        dispatchSubscriptionOverride(listener, subId, overrideMask, overrideValue,
-                                networkTypeMask);
+                        dispatchSubscriptionOverride(listener, subId, overrideMask, overrideValue);
                     }
                     mListeners.finishBroadcast();
                     return true;
@@ -4576,6 +4571,17 @@
                     setNetworkTemplateEnabledInner(template, enabled);
                     return true;
                 }
+                case MSG_SUBSCRIPTION_PLANS_CHANGED: {
+                    final SubscriptionPlan[] plans = (SubscriptionPlan[]) msg.obj;
+                    final int subId = msg.arg1;
+                    final int length = mListeners.beginBroadcast();
+                    for (int i = 0; i < length; i++) {
+                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+                        dispatchSubscriptionPlansChanged(listener, subId, plans);
+                    }
+                    mListeners.finishBroadcast();
+                    return true;
+                }
                 default: {
                     return false;
                 }
@@ -4727,7 +4733,7 @@
     }
 
     /**
-     * Calls {@link #setUidFirewallRules(int, SparseIntArray)} and
+     * Calls {@link #setUidFirewallRulesUL(int, SparseIntArray)} and
      * {@link #enableFirewallChainUL(int, boolean)} synchronously.
      *
      * @param chain firewall chain.
diff --git a/services/core/java/com/android/server/net/watchlist/HarmfulCrcs.java b/services/core/java/com/android/server/net/watchlist/HarmfulCrcs.java
new file mode 100644
index 0000000..65a4b23
--- /dev/null
+++ b/services/core/java/com/android/server/net/watchlist/HarmfulCrcs.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net.watchlist;
+
+import com.android.internal.util.HexDump;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Helper class to store a set of harmful CRC32s in memory.
+ * TODO: Optimize memory usage using int array with binary search.
+ */
+class HarmfulCrcs {
+
+    private final Set<Integer> mCrcSet;
+
+    HarmfulCrcs(List<byte[]> digests) {
+        final HashSet<Integer> crcSet = new HashSet<>();
+        final int size = digests.size();
+        for (int i = 0; i < size; i++) {
+            byte[] bytes = digests.get(i);
+            if (bytes.length <= 4) {
+                int crc = 0;
+                for (byte b : bytes) {
+                    // Remember byte is signed
+                    crc = (crc << 8) | (b & 0xff);
+                }
+                crcSet.add(crc);
+            }
+        }
+        mCrcSet = Collections.unmodifiableSet(crcSet);
+    }
+
+    public boolean contains(int crc) {
+        return mCrcSet.contains(crc);
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        for (int crc : mCrcSet) {
+            pw.println(HexDump.toHexString(crc));
+        }
+        pw.println("");
+    }
+}
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java b/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
index 8352ca6..7d06de3 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
@@ -18,7 +18,6 @@
 
 import android.annotation.Nullable;
 import android.os.FileUtils;
-import android.util.AtomicFile;
 import android.util.Log;
 import android.util.Slog;
 import android.util.Xml;
@@ -66,11 +65,11 @@
     }
 
     private static class CrcShaDigests {
-        final HarmfulDigests crc32Digests;
-        final HarmfulDigests sha256Digests;
+        public final HarmfulCrcs crc32s;
+        public final HarmfulDigests sha256Digests;
 
-        public CrcShaDigests(HarmfulDigests crc32Digests, HarmfulDigests sha256Digests) {
-            this.crc32Digests = crc32Digests;
+        CrcShaDigests(HarmfulCrcs crc32s, HarmfulDigests sha256Digests) {
+            this.crc32s = crc32s;
             this.sha256Digests = sha256Digests;
         }
     }
@@ -140,9 +139,9 @@
                 }
             }
             parser.require(XmlPullParser.END_TAG, null, XmlTags.WATCHLIST_CONFIG);
-            mDomainDigests = new CrcShaDigests(new HarmfulDigests(crc32DomainList),
+            mDomainDigests = new CrcShaDigests(new HarmfulCrcs(crc32DomainList),
                     new HarmfulDigests(sha256DomainList));
-            mIpDigests = new CrcShaDigests(new HarmfulDigests(crc32IpList),
+            mIpDigests = new CrcShaDigests(new HarmfulCrcs(crc32IpList),
                     new HarmfulDigests(sha256IpList));
             Log.i(TAG, "Reload watchlist done");
         } catch (IllegalStateException | NullPointerException | NumberFormatException |
@@ -171,8 +170,8 @@
             return false;
         }
         // First it does a quick CRC32 check.
-        final byte[] crc32 = getCrc32(domain);
-        if (!domainDigests.crc32Digests.contains(crc32)) {
+        final int crc32 = getCrc32(domain);
+        if (!domainDigests.crc32s.contains(crc32)) {
             return false;
         }
         // Now we do a slow SHA256 check.
@@ -187,8 +186,8 @@
             return false;
         }
         // First it does a quick CRC32 check.
-        final byte[] crc32 = getCrc32(ip);
-        if (!ipDigests.crc32Digests.contains(crc32)) {
+        final int crc32 = getCrc32(ip);
+        if (!ipDigests.crc32s.contains(crc32)) {
             return false;
         }
         // Now we do a slow SHA256 check.
@@ -198,15 +197,11 @@
 
 
     /** Get CRC32 of a string
-     *
-     * TODO: Review if we should use CRC32 or other algorithms
      */
-    private byte[] getCrc32(String str) {
+    private int getCrc32(String str) {
         final CRC32 crc = new CRC32();
         crc.update(str.getBytes());
-        final long tmp = crc.getValue();
-        return new byte[]{(byte) (tmp >> 24 & 255), (byte) (tmp >> 16 & 255),
-                (byte) (tmp >> 8 & 255), (byte) (tmp & 255)};
+        return (int) crc.getValue();
     }
 
     /** Get SHA256 of a string */
@@ -279,7 +274,7 @@
         pw.println("Domain CRC32 digest list:");
         // mDomainDigests won't go from non-null to null so it's safe
         if (mDomainDigests != null) {
-            mDomainDigests.crc32Digests.dump(fd, pw, args);
+            mDomainDigests.crc32s.dump(fd, pw, args);
         }
         pw.println("Domain SHA256 digest list:");
         if (mDomainDigests != null) {
@@ -288,7 +283,7 @@
         pw.println("Ip CRC32 digest list:");
         // mIpDigests won't go from non-null to null so it's safe
         if (mIpDigests != null) {
-            mIpDigests.crc32Digests.dump(fd, pw, args);
+            mIpDigests.crc32s.dump(fd, pw, args);
         }
         pw.println("Ip SHA256 digest list:");
         if (mIpDigests != null) {
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 61be1f5..6f0ad33 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -17,6 +17,7 @@
 package com.android.server.notification;
 
 import android.app.Notification;
+import android.net.Uri;
 import android.service.notification.NotificationStats;
 
 import com.android.internal.statusbar.NotificationVisibility;
@@ -49,6 +50,12 @@
     void onNotificationBubbleChanged(String key, boolean isBubble);
 
     /**
+     * Grant permission to read the specified URI to the package associated with the
+     * NotificationRecord associated with the given key.
+     */
+    void grantInlineReplyUriPermission(String key, Uri uri, int callingUid);
+
+    /**
      * Notifies that smart replies and actions have been added to the UI.
      */
     void onNotificationSmartSuggestionsAdded(String key, int smartReplyCount, int smartActionCount,
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4457e9c..cd3343b 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -21,6 +21,7 @@
 import static android.app.Notification.FLAG_AUTOGROUP_SUMMARY;
 import static android.app.Notification.FLAG_BUBBLE;
 import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
+import static android.app.Notification.FLAG_INSISTENT;
 import static android.app.Notification.FLAG_NO_CLEAR;
 import static android.app.Notification.FLAG_ONGOING_EVENT;
 import static android.app.Notification.FLAG_ONLY_ALERT_ONCE;
@@ -55,6 +56,7 @@
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
 import static android.os.UserHandle.USER_NULL;
@@ -1154,6 +1156,56 @@
                 }
             }
         }
+
+        @Override
+        /**
+         * Grant permission to read the specified URI to the package specified in the
+         * NotificationRecord associated with the given key. The callingUid represents the UID of
+         * SystemUI from which this method is being called.
+         *
+         * For this to work, SystemUI must have permission to read the URI when running under the
+         * user associated with the NotificationRecord, and this grant will fail when trying
+         * to grant URI permissions across users.
+         */
+        public void grantInlineReplyUriPermission(String key, Uri uri, int callingUid) {
+            synchronized (mNotificationLock) {
+                NotificationRecord r = mNotificationsByKey.get(key);
+                if (r != null) {
+                    IBinder owner = r.permissionOwner;
+                    if (owner == null) {
+                        r.permissionOwner = mUgmInternal.newUriPermissionOwner("NOTIF:" + key);
+                        owner = r.permissionOwner;
+                    }
+                    int uid = callingUid;
+                    int userId = r.sbn.getUserId();
+                    if (userId == UserHandle.USER_ALL) {
+                        userId = USER_SYSTEM;
+                    }
+                    if (UserHandle.getUserId(uid) != userId) {
+                        try {
+                            final String[] pkgs = mPackageManager.getPackagesForUid(callingUid);
+                            if (pkgs == null) {
+                                Log.e(TAG, "Cannot grant uri permission to unknown UID: "
+                                        + callingUid);
+                            }
+                            final String pkg = pkgs[0]; // Get the SystemUI package
+                            // Find the UID for SystemUI for the correct user
+                            uid =  mPackageManager.getPackageUid(pkg, 0, userId);
+                        } catch (RemoteException re) {
+                            Log.e(TAG, "Cannot talk to package manager", re);
+                        }
+                    }
+                    grantUriPermission(owner, uri, uid, r.sbn.getPackageName(), userId);
+                } else {
+                    Log.w(TAG, "No record found for notification key:" + key);
+
+                    // TODO: figure out cancel story. I think it's: sysui needs to tell us
+                    // whenever noitifications held by a lifetimextender go away
+                    // IBinder owner = mUgmInternal.newUriPermissionOwner("InlineReply:" + key);
+                    // pass in userId and package as well as key (key for logging purposes)
+                }
+            }
+        }
     };
 
     @VisibleForTesting
@@ -1183,7 +1235,7 @@
     }
 
     @GuardedBy("mNotificationLock")
-    private void clearSoundLocked() {
+    void clearSoundLocked() {
         mSoundNotificationKey = null;
         long identity = Binder.clearCallingIdentity();
         try {
@@ -1198,7 +1250,7 @@
     }
 
     @GuardedBy("mNotificationLock")
-    private void clearVibrateLocked() {
+    void clearVibrateLocked() {
         mVibrateNotificationKey = null;
         long identity = Binder.clearCallingIdentity();
         try {
@@ -4495,13 +4547,13 @@
         if (record != null && record.getAudioAttributes() != null) {
             if ((mListenerHints & HINT_HOST_DISABLE_NOTIFICATION_EFFECTS) != 0) {
                 if (record.getAudioAttributes().getUsage()
-                        != AudioAttributes.USAGE_VOICE_COMMUNICATION) {
+                        != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
                     return "listenerNoti";
                 }
             }
             if ((mListenerHints & HINT_HOST_DISABLE_CALL_EFFECTS) != 0) {
                 if (record.getAudioAttributes().getUsage()
-                        == AudioAttributes.USAGE_VOICE_COMMUNICATION) {
+                        == AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
                     return "listenerCall";
                 }
             }
@@ -5060,8 +5112,8 @@
         }
         if (contentViewSize >= mStripRemoteViewsSizeBytes) {
             mUsageStats.registerImageRemoved(pkg);
-            Slog.w(TAG,
-                    "Removed too large RemoteViews on pkg: " + pkg + " tag: " + tag + " id: " + id);
+            Slog.w(TAG, "Removed too large RemoteViews (" + contentViewSize + " bytes) on pkg: "
+                    + pkg + " tag: " + tag + " id: " + id);
             return true;
         }
         return false;
@@ -6060,7 +6112,6 @@
                 mIsAutomotive
                         ? record.getImportance() > NotificationManager.IMPORTANCE_DEFAULT
                         : record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT;
-
         // Remember if this notification already owns the notification channels.
         boolean wasBeep = key != null && key.equals(mSoundNotificationKey);
         boolean wasBuzz = key != null && key.equals(mVibrateNotificationKey);
@@ -6076,7 +6127,6 @@
         }
 
         if (aboveThreshold && isNotificationForCurrentUser(record)) {
-
             if (mSystemReady && mAudioManager != null) {
                 Uri soundUri = record.getSound();
                 hasValidSound = soundUri != null && !Uri.EMPTY.equals(soundUri);
@@ -6091,7 +6141,6 @@
                     vibration = mFallbackVibrationPattern;
                 }
                 hasValidVibrate = vibration != null;
-
                 boolean hasAudibleAlert = hasValidSound || hasValidVibrate;
                 if (hasAudibleAlert && !shouldMuteNotificationLocked(record)) {
                     if (!sentAccessibilityEvent) {
@@ -6248,11 +6297,29 @@
             return true;
         }
 
+        // A looping ringtone, such as an incoming call is playing
+        if (isLoopingRingtoneNotification(mNotificationsByKey.get(mSoundNotificationKey))
+                || isLoopingRingtoneNotification(
+                        mNotificationsByKey.get(mVibrateNotificationKey))) {
+            return true;
+        }
+
+        return false;
+    }
+
+    @GuardedBy("mNotificationLock")
+    private boolean isLoopingRingtoneNotification(final NotificationRecord playingRecord) {
+        if (playingRecord != null) {
+            if (playingRecord.getAudioAttributes().getUsage() == USAGE_NOTIFICATION_RINGTONE
+                    && (playingRecord.getNotification().flags & FLAG_INSISTENT) != 0) {
+                return true;
+            }
+        }
         return false;
     }
 
     private boolean playSound(final NotificationRecord record, Uri soundUri) {
-        boolean looping = (record.getNotification().flags & Notification.FLAG_INSISTENT) != 0;
+        boolean looping = (record.getNotification().flags & FLAG_INSISTENT) != 0;
         // play notifications if there is no user of exclusive audio focus
         // and the stream volume is not 0 (non-zero volume implies not silenced by SILENT or
         //   VIBRATE ringer mode)
@@ -6304,7 +6371,6 @@
                     try {
                         Thread.sleep(waitMs);
                     } catch (InterruptedException e) { }
-
                     // Notifications might be canceled before it actually vibrates due to waitMs,
                     // so need to check the notification still valide for vibrate.
                     synchronized (mNotificationLock) {
@@ -7012,7 +7078,6 @@
     private void grantUriPermission(IBinder owner, Uri uri, int sourceUid, String targetPkg,
             int targetUserId) {
         if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return;
-
         final long ident = Binder.clearCallingIdentity();
         try {
             mUgm.grantUriPermissionFromOwner(owner, sourceUid, targetPkg,
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 05b6168..c8179a7 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -131,7 +131,7 @@
 
     private static class FeatureConfigImpl implements FeatureConfig {
         private static final String FILTERING_ENABLED_NAME = "package_query_filtering_enabled";
-        private volatile boolean mFeatureEnabled = true;
+        private volatile boolean mFeatureEnabled = false;
         private CompatConfig mCompatibility;
 
         private FeatureConfigImpl(PackageManagerService.Injector injector) {
@@ -141,12 +141,12 @@
         @Override
         public void onSystemReady() {
             mFeatureEnabled = DeviceConfig.getBoolean(
-                    NAMESPACE_PACKAGE_MANAGER_SERVICE, FILTERING_ENABLED_NAME, true);
+                    NAMESPACE_PACKAGE_MANAGER_SERVICE, FILTERING_ENABLED_NAME, false);
             DeviceConfig.addOnPropertiesChangedListener(
                     NAMESPACE_PACKAGE_MANAGER_SERVICE, FgThread.getExecutor(),
                     properties -> {
                         synchronized (FeatureConfigImpl.this) {
-                            mFeatureEnabled = properties.getBoolean(FILTERING_ENABLED_NAME, true);
+                            mFeatureEnabled = properties.getBoolean(FILTERING_ENABLED_NAME, false);
                         }
                     });
         }
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
index 976cdfb..b1eb7e7 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -50,6 +50,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ArrayUtils;
 import com.android.server.IntentResolver;
 
 import java.io.PrintWriter;
@@ -386,8 +387,11 @@
             addProvidersLocked(pkg, chatty);
             addServicesLocked(pkg, chatty);
         }
-        final String setupWizardPackage = sPackageManagerInternal.getKnownPackageName(
-                PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM);
+        // expect single setupwizard package
+        final String setupWizardPackage = ArrayUtils.firstOrNull(
+                sPackageManagerInternal.getKnownPackageNames(
+                        PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM));
+
         for (int i = newIntents.size() - 1; i >= 0; --i) {
             final PackageParser.ActivityIntentInfo intentInfo = newIntents.get(i);
             final PackageParser.Package disabledPkg = sPackageManagerInternal
@@ -421,8 +425,11 @@
         final List<ActivityIntentInfo> protectedFilters = mProtectedFilters;
         mProtectedFilters = null;
 
-        final String setupWizardPackage = sPackageManagerInternal.getKnownPackageName(
-                PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM);
+        // expect single setupwizard package
+        final String setupWizardPackage = ArrayUtils.firstOrNull(
+                sPackageManagerInternal.getKnownPackageNames(
+                        PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM));
+
         if (DEBUG_FILTERS && setupWizardPackage == null) {
             Slog.i(TAG, "No setup wizard;"
                     + " All protected intents capped to priority 0");
diff --git a/services/core/java/com/android/server/pm/InstallSource.java b/services/core/java/com/android/server/pm/InstallSource.java
new file mode 100644
index 0000000..990eba1
--- /dev/null
+++ b/services/core/java/com/android/server/pm/InstallSource.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.annotation.Nullable;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.util.Objects;
+
+/**
+ * Immutable class holding information about where the request to install or update an app
+ * came from.
+ */
+final class InstallSource {
+    /**
+     * An instance of InstallSource representing an absence of knowledge of the source of
+     * a package. Used in preference to null.
+     */
+    static final InstallSource EMPTY = new InstallSource(null, null, false);
+
+    /** The package that requested the installation, if known. */
+    @Nullable
+    final String initiatingPackageName;
+
+    /**
+     * Package name of the app that installed this package (the installer of record). Note that
+     * this may be modified.
+     */
+    @Nullable
+    final String installerPackageName;
+
+    /** Indicates if the package that was the installerPackageName has been uninstalled. */
+    final boolean isOrphaned;
+
+    static InstallSource create(@Nullable String initiatingPackageName,
+            @Nullable String installerPackageName) {
+        return create(initiatingPackageName, installerPackageName, false);
+    }
+
+    static InstallSource create(@Nullable String initiatingPackageName,
+            @Nullable String installerPackageName, boolean isOrphaned) {
+        if (initiatingPackageName == null && installerPackageName == null && !isOrphaned) {
+            return EMPTY;
+        }
+        return new InstallSource(
+                initiatingPackageName == null ? null : initiatingPackageName.intern(),
+                installerPackageName == null ? null : installerPackageName.intern(),
+                isOrphaned);
+    }
+
+    private InstallSource(@Nullable String initiatingPackageName,
+            @Nullable String installerPackageName, boolean isOrphaned) {
+        this.initiatingPackageName = initiatingPackageName;
+        this.isOrphaned = isOrphaned;
+        this.installerPackageName = installerPackageName;
+    }
+
+    void dump(IndentingPrintWriter pw) {
+        pw.printPair("installerPackageName", installerPackageName);
+        pw.printPair("installInitiatingPackageName", initiatingPackageName);
+    }
+
+    /**
+     * Return an InstallSource the same as this one except with the specified installerPackageName.
+     */
+    InstallSource setInstallerPackage(String installerPackageName) {
+        return Objects.equals(installerPackageName, this.installerPackageName) ? this
+                : create(initiatingPackageName, installerPackageName, isOrphaned);
+    }
+
+    /**
+     * Return an InstallSource the same as this one except with the specified value for isOrphaned.
+     */
+    InstallSource setIsOrphaned(boolean isOrphaned) {
+        return isOrphaned == this.isOrphaned ? this
+                : create(initiatingPackageName, installerPackageName, isOrphaned);
+    }
+
+    /**
+     * Return an InstallSource the same as this one except it does not refer to the specified
+     * installer package name (which is being uninstalled).
+     */
+    InstallSource removeInstallerPackage(String packageName) {
+        if (packageName == null) {
+            return this;
+        }
+
+        boolean modified = false;
+        String initiatingPackageName = this.initiatingPackageName;
+        String installerPackageName = this.installerPackageName;
+        boolean isOrphaned = this.isOrphaned;
+
+        if (packageName.equals(initiatingPackageName)) {
+            initiatingPackageName = null;
+            modified = true;
+        }
+        if (packageName.equals(installerPackageName)) {
+            installerPackageName = null;
+            isOrphaned = true;
+            modified = true;
+        }
+
+        return modified
+                ? create(initiatingPackageName, installerPackageName, isOrphaned)
+                : this;
+    }
+}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index a7d4237..00c0566 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -482,15 +482,24 @@
             throw new SecurityException("User restriction prevents installing");
         }
 
+        String requestedInstallerPackageName = params.installerPackageName != null
+                ? params.installerPackageName : installerPackageName;
+
         if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
             params.installFlags |= PackageManager.INSTALL_FROM_ADB;
 
         } else {
+            if (callingUid != Process.SYSTEM_UID) {
+                // The supplied installerPackageName must always belong to the calling app.
+                mAppOps.checkPackage(callingUid, installerPackageName);
+            }
             // Only apps with INSTALL_PACKAGES are allowed to set an installer that is not the
             // caller.
-            if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES) !=
-                    PackageManager.PERMISSION_GRANTED) {
-                mAppOps.checkPackage(callingUid, installerPackageName);
+            if (!requestedInstallerPackageName.equals(installerPackageName)) {
+                if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES)
+                        != PackageManager.PERMISSION_GRANTED) {
+                    mAppOps.checkPackage(callingUid, requestedInstallerPackageName);
+                }
             }
 
             params.installFlags &= ~PackageManager.INSTALL_FROM_ADB;
@@ -614,11 +623,13 @@
                 stageCid = buildExternalStageCid(sessionId);
             }
         }
+        InstallSource installSource = InstallSource.create(installerPackageName,
+                requestedInstallerPackageName);
         session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
-                mInstallThread.getLooper(), mStagingManager, sessionId, userId,
-                installerPackageName, callingUid, params, createdMillis, stageDir, stageCid, false,
-                false, false, null, SessionInfo.INVALID_ID, false, false, false,
-                SessionInfo.STAGED_SESSION_NO_ERROR, "");
+                mInstallThread.getLooper(), mStagingManager, sessionId, userId, callingUid,
+                installSource, params, createdMillis,
+                stageDir, stageCid, false, false, false, null, SessionInfo.INVALID_ID,
+                false, false, false, SessionInfo.STAGED_SESSION_NO_ERROR, "");
 
         synchronized (mSessions) {
             mSessions.put(sessionId, session);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index b720290..feb1271 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -146,6 +146,8 @@
     private static final String ATTR_USER_ID = "userId";
     private static final String ATTR_INSTALLER_PACKAGE_NAME = "installerPackageName";
     private static final String ATTR_INSTALLER_UID = "installerUid";
+    private static final String ATTR_INITIATING_PACKAGE_NAME =
+            "installInitiatingPackageName";
     private static final String ATTR_CREATED_MILLIS = "createdMillis";
     private static final String ATTR_UPDATED_MILLIS = "updatedMillis";
     private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
@@ -210,14 +212,14 @@
     /** Uid of the creator of this session. */
     private final int mOriginalInstallerUid;
 
-    /** Package of the owner of the installer session */
-    @GuardedBy("mLock")
-    private @Nullable String mInstallerPackageName;
-
     /** Uid of the owner of the installer session */
     @GuardedBy("mLock")
     private int mInstallerUid;
 
+    /** Where this install request came from */
+    @GuardedBy("mLock")
+    private InstallSource mInstallSource;
+
     @GuardedBy("mLock")
     private float mClientProgress = 0;
     @GuardedBy("mLock")
@@ -368,7 +370,8 @@
         }
         DevicePolicyManagerInternal dpmi =
                 LocalServices.getService(DevicePolicyManagerInternal.class);
-        return dpmi != null && dpmi.canSilentlyInstallPackage(mInstallerPackageName, mInstallerUid);
+        return dpmi != null && dpmi.canSilentlyInstallPackage(
+                mInstallSource.installerPackageName, mInstallerUid);
     }
 
     /**
@@ -412,8 +415,8 @@
     public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
             Context context, PackageManagerService pm,
             PackageSessionProvider sessionProvider, Looper looper, StagingManager stagingManager,
-            int sessionId, int userId,
-            String installerPackageName, int installerUid, SessionParams params, long createdMillis,
+            int sessionId, int userId, int installerUid, @NonNull InstallSource installSource,
+            SessionParams params, long createdMillis,
             File stageDir, String stageCid, boolean prepared, boolean committed, boolean sealed,
             @Nullable int[] childSessionIds, int parentSessionId, boolean isReady,
             boolean isFailed, boolean isApplied, int stagedSessionErrorCode,
@@ -428,8 +431,8 @@
         this.sessionId = sessionId;
         this.userId = userId;
         mOriginalInstallerUid = installerUid;
-        mInstallerPackageName = installerPackageName;
         mInstallerUid = installerUid;
+        mInstallSource = Preconditions.checkNotNull(installSource);
         this.params = params;
         this.createdMillis = createdMillis;
         this.updatedMillis = createdMillis;
@@ -467,7 +470,7 @@
         synchronized (mLock) {
             info.sessionId = sessionId;
             info.userId = userId;
-            info.installerPackageName = mInstallerPackageName;
+            info.installerPackageName = mInstallSource.installerPackageName;
             info.resolvedBaseCodePath = (mResolvedBaseFile != null) ?
                     mResolvedBaseFile.getAbsolutePath() : null;
             info.progress = mProgress;
@@ -1218,13 +1221,13 @@
                 throw new IllegalArgumentException("Package is not valid", e);
             }
 
-            if (!mPackageName.equals(mInstallerPackageName)) {
+            if (!mPackageName.equals(mInstallSource.installerPackageName)) {
                 throw new SecurityException("Can only transfer sessions that update the original "
                         + "installer");
             }
 
-            mInstallerPackageName = packageName;
             mInstallerUid = newOwnerAppInfo.uid;
+            mInstallSource = InstallSource.create(packageName, packageName);
         }
 
         // Persist the fact that we've sealed ourselves to prevent
@@ -1237,7 +1240,7 @@
         if (isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked()) {
             DevicePolicyEventLogger
                     .createEvent(DevicePolicyEnums.INSTALL_PACKAGE)
-                    .setAdmin(mInstallerPackageName)
+                    .setAdmin(mInstallSource.installerPackageName)
                     .write();
         }
         if (params.isStaged) {
@@ -1443,8 +1446,7 @@
 
         mRelinquished = true;
         return new PackageManagerService.ActiveInstallSession(mPackageName, stageDir,
-                localObserver, params, mInstallerPackageName, mInstallerUid, user,
-                mSigningDetails);
+                localObserver, params, mInstallerUid, mInstallSource, user, mSigningDetails);
     }
 
     private static void maybeRenameFile(File from, File to) throws PackageManagerException {
@@ -1893,7 +1895,7 @@
 
     String getInstallerPackageName() {
         synchronized (mLock) {
-            return mInstallerPackageName;
+            return mInstallSource.installerPackageName;
         }
     }
 
@@ -2334,7 +2336,7 @@
 
         pw.printPair("userId", userId);
         pw.printPair("mOriginalInstallerUid", mOriginalInstallerUid);
-        pw.printPair("mInstallerPackageName", mInstallerPackageName);
+        mInstallSource.dump(pw);
         pw.printPair("mInstallerUid", mInstallerUid);
         pw.printPair("createdMillis", createdMillis);
         pw.printPair("updatedMillis", updatedMillis);
@@ -2414,8 +2416,10 @@
             writeIntAttribute(out, ATTR_SESSION_ID, sessionId);
             writeIntAttribute(out, ATTR_USER_ID, userId);
             writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME,
-                    mInstallerPackageName);
+                    mInstallSource.installerPackageName);
             writeIntAttribute(out, ATTR_INSTALLER_UID, mInstallerUid);
+            writeStringAttribute(out, ATTR_INITIATING_PACKAGE_NAME,
+                    mInstallSource.initiatingPackageName);
             writeLongAttribute(out, ATTR_CREATED_MILLIS, createdMillis);
             writeLongAttribute(out, ATTR_UPDATED_MILLIS, updatedMillis);
             if (stageDir != null) {
@@ -2521,6 +2525,8 @@
         final String installerPackageName = readStringAttribute(in, ATTR_INSTALLER_PACKAGE_NAME);
         final int installerUid = readIntAttribute(in, ATTR_INSTALLER_UID, pm.getPackageUid(
                 installerPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId));
+        final String installInitiatingPackageName =
+                readStringAttribute(in, ATTR_INITIATING_PACKAGE_NAME);
         final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
         long updatedMillis = readLongAttribute(in, ATTR_UPDATED_MILLIS);
         final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR);
@@ -2612,17 +2618,12 @@
             childSessionIdsArray = EMPTY_CHILD_SESSION_ARRAY;
         }
 
+        InstallSource installSource = InstallSource.create(installInitiatingPackageName,
+                installerPackageName);
         return new PackageInstallerSession(callback, context, pm, sessionProvider,
-                installerThread, stagingManager, sessionId, userId, installerPackageName,
-                installerUid, params, createdMillis, stageDir, stageCid, prepared, committed,
-                sealed, childSessionIdsArray, parentSessionId, isReady, isFailed, isApplied,
-                stagedSessionErrorCode, stagedSessionErrorMessage);
-    }
-
-    /**
-     * Reads the session ID from a child session tag stored in the provided {@link XmlPullParser}
-     */
-    static int readChildSessionIdFromXml(@NonNull XmlPullParser in) {
-        return readIntAttribute(in, ATTR_SESSION_ID, SessionInfo.INVALID_ID);
+                installerThread, stagingManager, sessionId, userId, installerUid,
+                installSource, params, createdMillis, stageDir, stageCid,
+                prepared, committed, sealed, childSessionIdsArray, parentSessionId,
+                isReady, isFailed, isApplied, stagedSessionErrorCode, stagedSessionErrorMessage);
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 67d0f62..0a4415b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -974,124 +974,9 @@
         @Override public final boolean hasFeature(String feature) {
             return PackageManagerService.this.hasSystemFeature(feature, 0);
         }
-
-        final List<PackageParser.Package> getStaticOverlayPackages(
-                Collection<PackageParser.Package> allPackages, String targetPackageName) {
-            if ("android".equals(targetPackageName)) {
-                // Static RROs targeting to "android", ie framework-res.apk, are already applied by
-                // native AssetManager.
-                return null;
-            }
-
-            List<PackageParser.Package> overlayPackages = null;
-            for (PackageParser.Package p : allPackages) {
-                if (targetPackageName.equals(p.mOverlayTarget) && p.mOverlayIsStatic) {
-                    if (overlayPackages == null) {
-                        overlayPackages = new ArrayList<>();
-                    }
-                    overlayPackages.add(p);
-                }
-            }
-            if (overlayPackages != null) {
-                Comparator<PackageParser.Package> cmp =
-                        Comparator.comparingInt(p -> p.mOverlayPriority);
-                overlayPackages.sort(cmp);
-            }
-            return overlayPackages;
-        }
-
-        final String[] getStaticOverlayPaths(List<PackageParser.Package> overlayPackages,
-                String targetPath) {
-            if (overlayPackages == null || overlayPackages.isEmpty()) {
-                return null;
-            }
-            List<String> overlayPathList = null;
-            for (PackageParser.Package overlayPackage : overlayPackages) {
-                if (targetPath == null) {
-                    if (overlayPathList == null) {
-                        overlayPathList = new ArrayList<>();
-                    }
-                    overlayPathList.add(overlayPackage.baseCodePath);
-                    continue;
-                }
-
-                try {
-                    // Creates idmaps for system to parse correctly the Android manifest of the
-                    // target package.
-                    //
-                    // OverlayManagerService will update each of them with a correct gid from its
-                    // target package app id.
-                    mInstaller.idmap(targetPath, overlayPackage.baseCodePath,
-                            UserHandle.getSharedAppGid(
-                                    UserHandle.getUserGid(UserHandle.USER_SYSTEM)));
-                    if (overlayPathList == null) {
-                        overlayPathList = new ArrayList<>();
-                    }
-                    overlayPathList.add(overlayPackage.baseCodePath);
-                } catch (InstallerException e) {
-                    Slog.e(TAG, "Failed to generate idmap for " + targetPath + " and " +
-                            overlayPackage.baseCodePath);
-                }
-            }
-            return overlayPathList == null ? null : overlayPathList.toArray(new String[0]);
-        }
-
-        String[] getStaticOverlayPaths(String targetPackageName, String targetPath) {
-            List<PackageParser.Package> overlayPackages;
-            synchronized (mInstallLock) {
-                synchronized (mLock) {
-                    overlayPackages = getStaticOverlayPackages(
-                            mPackages.values(), targetPackageName);
-                }
-                // It is safe to keep overlayPackages without holding mPackages because static overlay
-                // packages can't be uninstalled or disabled.
-                return getStaticOverlayPaths(overlayPackages, targetPath);
-            }
-        }
-
-        @Override public final String[] getOverlayApks(String targetPackageName) {
-            return getStaticOverlayPaths(targetPackageName, null);
-        }
-
-        @Override public final String[] getOverlayPaths(String targetPackageName,
-                String targetPath) {
-            return getStaticOverlayPaths(targetPackageName, targetPath);
-        }
-    }
-
-    class ParallelPackageParserCallback extends PackageParserCallback {
-        List<PackageParser.Package> mOverlayPackages = null;
-
-        void findStaticOverlayPackages() {
-            synchronized (mLock) {
-                for (PackageParser.Package p : mPackages.values()) {
-                    if (p.mOverlayIsStatic) {
-                        if (mOverlayPackages == null) {
-                            mOverlayPackages = new ArrayList<>();
-                        }
-                        mOverlayPackages.add(p);
-                    }
-                }
-            }
-        }
-
-        @Override
-        synchronized String[] getStaticOverlayPaths(String targetPackageName, String targetPath) {
-            // We can trust mOverlayPackages without holding mPackages because package uninstall
-            // can't happen while running parallel parsing.
-            // And we can call mInstaller inside getStaticOverlayPaths without holding mInstallLock
-            // because mInstallLock is held before running parallel parsing.
-            // Moreover holding mPackages or mInstallLock on each parsing thread causes dead-lock.
-            return mOverlayPackages == null ? null :
-                    getStaticOverlayPaths(
-                            getStaticOverlayPackages(mOverlayPackages, targetPackageName),
-                            targetPath);
-        }
     }
 
     final PackageParser.Callback mPackageParserCallback = new PackageParserCallback();
-    final ParallelPackageParserCallback mParallelPackageParserCallback =
-            new ParallelPackageParserCallback();
 
     // Currently known shared libraries.
     final ArrayMap<String, LongSparseArray<SharedLibraryInfo>> mSharedLibraries = new ArrayMap<>();
@@ -1603,6 +1488,8 @@
     final @Nullable String mConfiguratorPackage;
     final @Nullable String mAppPredictionServicePackage;
     final @Nullable String mIncidentReportApproverPackage;
+    final @Nullable String[] mTelephonyPackages;
+    final @Nullable String mWifiPackage;
     final @NonNull String mServicesSystemSharedLibraryPackageName;
     final @NonNull String mSharedSystemSharedLibraryPackageName;
 
@@ -1711,7 +1598,7 @@
                         handlePackagePostInstall(parentRes, grantPermissions,
                                 killApp, virtualPreload, grantedPermissions,
                                 whitelistedRestrictedPermissions, didRestore,
-                                args.installerPackageName, args.observer);
+                                args.installSource.installerPackageName, args.observer);
 
                         // Handle the child packages
                         final int childCount = (parentRes.addedChildPackages != null)
@@ -1721,7 +1608,7 @@
                             handlePackagePostInstall(childRes, grantPermissions,
                                     killApp, virtualPreload, grantedPermissions,
                                     whitelistedRestrictedPermissions, false /*didRestore*/,
-                                    args.installerPackageName, args.observer);
+                                    args.installSource.installerPackageName, args.observer);
                         }
 
                         // Log tracing if needed
@@ -2806,8 +2693,6 @@
                         systemScanFlags | partition.scanFlag, 0);
             }
 
-            mParallelPackageParserCallback.findStaticOverlayPackages();
-
             scanDirTracedLI(frameworkDir, systemParseFlags,
                     systemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0);
             if (!mPackages.containsKey("android")) {
@@ -3059,6 +2944,8 @@
                     mContext.getString(R.string.config_deviceConfiguratorPackageName);
             mAppPredictionServicePackage = getAppPredictionServicePackageName();
             mIncidentReportApproverPackage = getIncidentReportApproverPackageName();
+            mTelephonyPackages = getTelephonyPackageNames();
+            mWifiPackage = mContext.getString(R.string.config_wifiPackage);
 
             // Now that we know all of the shared libraries, update all clients to have
             // the correct library paths.
@@ -4150,7 +4037,7 @@
     private PackageInfo getPackageInfoInternal(String packageName, long versionCode,
             int flags, int filterCallingUid, int userId) {
         if (!mUserManager.exists(userId)) return null;
-        flags = updateFlagsForPackage(flags, userId, packageName);
+        flags = updateFlagsForPackage(flags, userId);
         mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */, "get package info");
 
@@ -4452,7 +4339,7 @@
     public int getPackageUid(String packageName, int flags, int userId) {
         if (!mUserManager.exists(userId)) return -1;
         final int callingUid = Binder.getCallingUid();
-        flags = updateFlagsForPackage(flags, userId, packageName);
+        flags = updateFlagsForPackage(flags, userId);
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /*requireFullPermission*/, false /*checkShell*/, "getPackageUid");
 
@@ -4482,7 +4369,7 @@
     public int[] getPackageGids(String packageName, int flags, int userId) {
         if (!mUserManager.exists(userId)) return null;
         final int callingUid = Binder.getCallingUid();
-        flags = updateFlagsForPackage(flags, userId, packageName);
+        flags = updateFlagsForPackage(flags, userId);
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /*requireFullPermission*/, false /*checkShell*/, "getPackageGids");
 
@@ -4564,7 +4451,7 @@
     private ApplicationInfo getApplicationInfoInternal(String packageName, int flags,
             int filterCallingUid, int userId) {
         if (!mUserManager.exists(userId)) return null;
-        flags = updateFlagsForApplication(flags, userId, packageName);
+        flags = updateFlagsForApplication(flags, userId);
 
         if (!isRecentsAccessingChildProfiles(Binder.getCallingUid(), userId)) {
             mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
@@ -4851,7 +4738,7 @@
     /**
      * Update given flags when being used to request {@link PackageInfo}.
      */
-    private int updateFlagsForPackage(int flags, int userId, Object cookie) {
+    private int updateFlagsForPackage(int flags, int userId) {
         final boolean isCallerSystemUser = UserHandle.getCallingUserId() == UserHandle.USER_SYSTEM;
         if ((flags & PackageManager.MATCH_ANY_USER) != 0) {
             // require the permission to be held; the calling uid and given user id referring
@@ -4875,14 +4762,14 @@
     /**
      * Update given flags when being used to request {@link ApplicationInfo}.
      */
-    private int updateFlagsForApplication(int flags, int userId, Object cookie) {
-        return updateFlagsForPackage(flags, userId, cookie);
+    private int updateFlagsForApplication(int flags, int userId) {
+        return updateFlagsForPackage(flags, userId);
     }
 
     /**
      * Update given flags when being used to request {@link ComponentInfo}.
      */
-    private int updateFlagsForComponent(int flags, int userId, Object cookie) {
+    private int updateFlagsForComponent(int flags, int userId) {
         return updateFlags(flags, userId);
     }
 
@@ -4911,16 +4798,12 @@
      * action and a {@code android.intent.category.BROWSABLE} category</li>
      * </ul>
      */
-    int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid) {
-        return updateFlagsForResolve(flags, userId, intent, callingUid,
-                false /*wantInstantApps*/, false /*onlyExposedExplicitly*/);
-    }
-    int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid,
-            boolean wantInstantApps) {
-        return updateFlagsForResolve(flags, userId, intent, callingUid,
+    int updateFlagsForResolve(int flags, int userId, int callingUid, boolean wantInstantApps) {
+        return updateFlagsForResolve(flags, userId, callingUid,
                 wantInstantApps, false /*onlyExposedExplicitly*/);
     }
-    int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid,
+
+    int updateFlagsForResolve(int flags, int userId, int callingUid,
             boolean wantInstantApps, boolean onlyExposedExplicitly) {
         // Safe mode means we shouldn't match any third-party components
         if (mSafeMode) {
@@ -4943,7 +4826,7 @@
                 flags &= ~PackageManager.MATCH_INSTANT;
             }
         }
-        return updateFlagsForComponent(flags, userId, intent /*cookie*/);
+        return updateFlagsForComponent(flags, userId);
     }
 
     @Override
@@ -4960,7 +4843,7 @@
     private ActivityInfo getActivityInfoInternal(ComponentName component, int flags,
             int filterCallingUid, int userId) {
         if (!mUserManager.exists(userId)) return null;
-        flags = updateFlagsForComponent(flags, userId, component);
+        flags = updateFlagsForComponent(flags, userId);
 
         if (!isRecentsAccessingChildProfiles(Binder.getCallingUid(), userId)) {
             mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
@@ -5041,7 +4924,7 @@
     public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
         if (!mUserManager.exists(userId)) return null;
         final int callingUid = Binder.getCallingUid();
-        flags = updateFlagsForComponent(flags, userId, component);
+        flags = updateFlagsForComponent(flags, userId);
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get receiver info");
         synchronized (mLock) {
@@ -5071,7 +4954,7 @@
             return null;
         }
 
-        flags = updateFlagsForPackage(flags, userId, null);
+        flags = updateFlagsForPackage(flags, userId);
 
         final boolean canSeeStaticLibraries =
                 mContext.checkCallingOrSelfPermission(INSTALL_PACKAGES)
@@ -5256,7 +5139,7 @@
     public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
         if (!mUserManager.exists(userId)) return null;
         final int callingUid = Binder.getCallingUid();
-        flags = updateFlagsForComponent(flags, userId, component);
+        flags = updateFlagsForComponent(flags, userId);
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get service info");
         synchronized (mLock) {
@@ -5281,7 +5164,7 @@
     public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
         if (!mUserManager.exists(userId)) return null;
         final int callingUid = Binder.getCallingUid();
-        flags = updateFlagsForComponent(flags, userId, component);
+        flags = updateFlagsForComponent(flags, userId);
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get provider info");
         synchronized (mLock) {
@@ -5981,7 +5864,7 @@
 
             if (!mUserManager.exists(userId)) return null;
             final int callingUid = Binder.getCallingUid();
-            flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart);
+            flags = updateFlagsForResolve(flags, userId, filterCallingUid, resolveForStart);
             mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                     false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
 
@@ -6011,7 +5894,7 @@
         intent = updateIntentForResolve(intent);
         final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
         final int flags = updateFlagsForResolve(
-                0, userId, intent, callingUid, false /*includeInstantApps*/);
+                0, userId, callingUid, false /*includeInstantApps*/);
         final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
                 userId);
         synchronized (mLock) {
@@ -6325,7 +6208,7 @@
                 android.provider.Settings.Global.getInt(mContext.getContentResolver(),
                         android.provider.Settings.Global.DEVICE_PROVISIONED, 0) == 1;
         flags = updateFlagsForResolve(
-                flags, userId, intent, callingUid, false /*includeInstantApps*/);
+                flags, userId, callingUid, false /*includeInstantApps*/);
         intent = updateIntentForResolve(intent);
         // writer
         synchronized (mLock) {
@@ -6533,7 +6416,7 @@
             final int callingUid = Binder.getCallingUid();
             final UserInfo parent = getProfileParent(sourceUserId);
             synchronized (mLock) {
-                int flags = updateFlagsForResolve(0, parent.id, intent, callingUid,
+                int flags = updateFlagsForResolve(0, parent.id, callingUid,
                         false /*includeInstantApps*/);
                 CrossProfileDomainInfo xpDomainInfo = getCrossProfileDomainPreferredLpr(
                         intent, resolvedType, flags, sourceUserId, parent.id);
@@ -6619,7 +6502,7 @@
             }
         }
 
-        flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart,
+        flags = updateFlagsForResolve(flags, userId, filterCallingUid, resolveForStart,
                 comp != null || pkgName != null /*onlyExposedExplicitly*/);
         if (comp != null) {
             final List<ResolveInfo> list = new ArrayList<>(1);
@@ -7386,8 +7269,7 @@
             String resolvedType, int flags, int userId) {
         if (!mUserManager.exists(userId)) return Collections.emptyList();
         final int callingUid = Binder.getCallingUid();
-        flags = updateFlagsForResolve(flags, userId, intent, callingUid,
-                false /*includeInstantApps*/);
+        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/);
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /*requireFullPermission*/, false /*checkShell*/,
                 "query intent activity options");
@@ -7573,8 +7455,7 @@
                 false /*requireFullPermission*/, false /*checkShell*/,
                 "query intent receivers");
         final String instantAppPkgName = getInstantAppPackageName(callingUid);
-        flags = updateFlagsForResolve(flags, userId, intent, callingUid,
-                false /*includeInstantApps*/);
+        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -7664,8 +7545,7 @@
     private ResolveInfo resolveServiceInternal(Intent intent, String resolvedType, int flags,
             int userId, int callingUid) {
         if (!mUserManager.exists(userId)) return null;
-        flags = updateFlagsForResolve(
-                flags, userId, intent, callingUid, false /*includeInstantApps*/);
+        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/);
         List<ResolveInfo> query = queryIntentServicesInternal(
                 intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/);
         if (query != null) {
@@ -7694,7 +7574,7 @@
                 false /*requireFullPermission*/, false /*checkShell*/,
                 "query intent receivers");
         final String instantAppPkgName = getInstantAppPackageName(callingUid);
-        flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps);
+        flags = updateFlagsForResolve(flags, userId, callingUid, includeInstantApps);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -7821,8 +7701,7 @@
         if (!mUserManager.exists(userId)) return Collections.emptyList();
         final int callingUid = Binder.getCallingUid();
         final String instantAppPkgName = getInstantAppPackageName(callingUid);
-        flags = updateFlagsForResolve(flags, userId, intent, callingUid,
-                false /*includeInstantApps*/);
+        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -7944,7 +7823,7 @@
             return ParceledListSlice.emptyList();
         }
         if (!mUserManager.exists(userId)) return ParceledListSlice.emptyList();
-        flags = updateFlagsForPackage(flags, userId, null);
+        flags = updateFlagsForPackage(flags, userId);
         final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
         final boolean listApex = (flags & MATCH_APEX) != 0;
         final boolean listFactory = (flags & MATCH_FACTORY_ONLY) != 0;
@@ -8044,7 +7923,7 @@
     public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
             String[] permissions, int flags, int userId) {
         if (!mUserManager.exists(userId)) return ParceledListSlice.emptyList();
-        flags = updateFlagsForPackage(flags, userId, permissions);
+        flags = updateFlagsForPackage(flags, userId);
         mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "get packages holding permissions");
@@ -8086,7 +7965,7 @@
             return Collections.emptyList();
         }
         if (!mUserManager.exists(userId)) return Collections.emptyList();
-        flags = updateFlagsForApplication(flags, userId, null);
+        flags = updateFlagsForApplication(flags, userId);
         final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
 
         mPermissionManager.enforceCrossUserPermission(
@@ -8321,7 +8200,7 @@
 
     private ProviderInfo resolveContentProviderInternal(String name, int flags, int userId) {
         if (!mUserManager.exists(userId)) return null;
-        flags = updateFlagsForComponent(flags, userId, name);
+        flags = updateFlagsForComponent(flags, userId);
         final int callingUid = Binder.getCallingUid();
         final ProviderInfo providerInfo = mComponentResolver.queryProvider(name, flags, userId);
         if (providerInfo == null) {
@@ -8360,7 +8239,7 @@
         final int userId = processName != null ? UserHandle.getUserId(uid)
                 : UserHandle.getCallingUserId();
         if (!mUserManager.exists(userId)) return ParceledListSlice.emptyList();
-        flags = updateFlagsForComponent(flags, userId, processName);
+        flags = updateFlagsForComponent(flags, userId);
         ArrayList<ProviderInfo> finalList = null;
         final List<ProviderInfo> matchList =
                 mComponentResolver.queryProviders(processName, metaDataKey, uid, flags, userId);
@@ -8467,7 +8346,7 @@
         }
         try (ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
                 mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
-                mParallelPackageParserCallback)) {
+                mPackageParserCallback)) {
             // Submit files for parsing in parallel
             int fileCount = 0;
             for (File file : files) {
@@ -10683,6 +10562,50 @@
         return changedAbiCodePath;
     }
 
+    /**
+     * Sets the enabled state of components configured through {@link SystemConfig}.
+     * This modifies the {@link PackageSetting} object.
+     **/
+    static void configurePackageComponents(PackageParser.Package pkg) {
+        final ArrayMap<String, Boolean> componentsEnabledStates = SystemConfig.getInstance()
+                .getComponentsEnabledStates(pkg.packageName);
+        if (componentsEnabledStates == null) {
+            return;
+        }
+
+        for (int i = pkg.activities.size() - 1; i >= 0; i--) {
+            final PackageParser.Activity component = pkg.activities.get(i);
+            final Boolean enabled = componentsEnabledStates.get(component.className);
+            if (enabled != null) {
+                component.info.enabled = enabled;
+            }
+        }
+
+        for (int i = pkg.receivers.size() - 1; i >= 0; i--) {
+            final PackageParser.Activity component = pkg.receivers.get(i);
+            final Boolean enabled = componentsEnabledStates.get(component.className);
+            if (enabled != null) {
+                component.info.enabled = enabled;
+            }
+        }
+
+        for (int i = pkg.providers.size() - 1; i >= 0; i--) {
+            final PackageParser.Provider component = pkg.providers.get(i);
+            final Boolean enabled = componentsEnabledStates.get(component.className);
+            if (enabled != null) {
+                component.info.enabled = enabled;
+            }
+        }
+
+        for (int i = pkg.services.size() - 1; i >= 0; i--) {
+            final PackageParser.Service component = pkg.services.get(i);
+            final Boolean enabled = componentsEnabledStates.get(component.className);
+            if (enabled != null) {
+                component.info.enabled = enabled;
+            }
+        }
+    }
+
 
     /**
      * Just scans the package without any side effects.
@@ -10850,6 +10773,10 @@
             pkg.applicationInfo.initForUser(UserHandle.USER_SYSTEM);
         }
 
+        if (pkg.isSystem()) {
+            configurePackageComponents(pkg);
+        }
+
         final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
 
         if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
@@ -10972,7 +10899,7 @@
         }
 
         if (isSystemApp(pkg)) {
-            pkgSetting.isOrphaned = true;
+            pkgSetting.setIsOrphaned(true);
         }
 
         // Take care of first install / last update times.
@@ -12455,7 +12382,7 @@
             int userId) {
         final PackageRemovedInfo info = new PackageRemovedInfo(this);
         info.removedPackage = packageName;
-        info.installerPackageName = pkgSetting.installerPackageName;
+        info.installerPackageName = pkgSetting.installSource.installerPackageName;
         info.removedUsers = new int[] {userId};
         info.broadcastUsers = new int[] {userId};
         info.uid = UserHandle.getUid(userId, pkgSetting.appId);
@@ -13477,9 +13404,11 @@
 
             // Verify: if target already has an installer package, it must
             // be signed with the same cert as the caller.
-            if (targetPackageSetting.installerPackageName != null) {
+            String targetInstallerPackageName =
+                    targetPackageSetting.installSource.installerPackageName;
+            if (targetInstallerPackageName != null) {
                 PackageSetting setting = mSettings.mPackages.get(
-                        targetPackageSetting.installerPackageName);
+                        targetInstallerPackageName);
                 // If the currently set package isn't valid, then it's always
                 // okay to change it.
                 if (setting != null) {
@@ -13488,13 +13417,13 @@
                             != PackageManager.SIGNATURE_MATCH) {
                         throw new SecurityException(
                                 "Caller does not have same cert as old installer package "
-                                + targetPackageSetting.installerPackageName);
+                                + targetInstallerPackageName);
                     }
                 }
             }
 
             // Okay!
-            targetPackageSetting.installerPackageName = installerPackageName;
+            targetPackageSetting.setInstallerPackageName(installerPackageName);
             if (installerPackageName != null) {
                 mSettings.mInstallerPackages.add(installerPackageName);
             }
@@ -13519,7 +13448,7 @@
                     ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
                 throw new IllegalArgumentException("Unknown target package " + packageName);
             }
-            if (!Objects.equals(callerPackageName, ps.installerPackageName)) {
+            if (!Objects.equals(callerPackageName, ps.installSource.installerPackageName)) {
                 throw new IllegalArgumentException("Calling package " + callerPackageName
                         + " is not installer for " + packageName);
             }
@@ -13979,7 +13908,7 @@
         final MoveInfo move;
         final IPackageInstallObserver2 observer;
         int installFlags;
-        final String installerPackageName;
+        @NonNull final InstallSource installSource;
         final String volumeUuid;
         private boolean mVerificationCompleted;
         private boolean mEnableRollbackCompleted;
@@ -13996,17 +13925,17 @@
         final long requiredInstalledVersionCode;
 
         InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
-                int installFlags, String installerPackageName, String volumeUuid,
+                int installFlags, InstallSource installSource, String volumeUuid,
                 VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
                 String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
-                PackageParser.SigningDetails signingDetails, int installReason,
+                SigningDetails signingDetails, int installReason,
                 long requiredInstalledVersionCode) {
             super(user);
             this.origin = origin;
             this.move = move;
             this.observer = observer;
             this.installFlags = installFlags;
-            this.installerPackageName = installerPackageName;
+            this.installSource = Preconditions.checkNotNull(installSource);
             this.volumeUuid = volumeUuid;
             this.verificationInfo = verificationInfo;
             this.packageAbiOverride = packageAbiOverride;
@@ -14032,12 +13961,13 @@
                     activeInstallSession.getInstallerUid());
             origin = OriginInfo.fromStagedFile(activeInstallSession.getStagedDir());
             move = null;
-            installReason = fixUpInstallReason(activeInstallSession.getInstallerPackageName(),
+            installReason = fixUpInstallReason(
+                    activeInstallSession.getInstallSource().installerPackageName,
                     activeInstallSession.getInstallerUid(),
                     activeInstallSession.getSessionParams().installReason);
             observer = activeInstallSession.getObserver();
             installFlags = activeInstallSession.getSessionParams().installFlags;
-            installerPackageName = activeInstallSession.getInstallerPackageName();
+            installSource = activeInstallSession.getInstallSource();
             volumeUuid = activeInstallSession.getSessionParams().volumeUuid;
             packageAbiOverride = activeInstallSession.getSessionParams().abiOverride;
             grantedRuntimePermissions = activeInstallSession.getSessionParams()
@@ -14288,7 +14218,7 @@
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
 
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
-                            installerPackageName);
+                            installSource.installerPackageName);
 
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS,
                             installFlags);
@@ -14519,7 +14449,7 @@
         final IPackageInstallObserver2 observer;
         // Always refers to PackageManager flags only
         final int installFlags;
-        final String installerPackageName;
+        @NonNull final InstallSource installSource;
         final String volumeUuid;
         final UserHandle user;
         final String abiOverride;
@@ -14538,7 +14468,7 @@
         /* nullable */ String[] instructionSets;
 
         InstallArgs(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
-                int installFlags, String installerPackageName, String volumeUuid,
+                int installFlags, InstallSource installSource, String volumeUuid,
                 UserHandle user, String[] instructionSets,
                 String abiOverride, String[] installGrantPermissions,
                 List<String> whitelistedRestrictedPermissions,
@@ -14549,7 +14479,7 @@
             this.move = move;
             this.installFlags = installFlags;
             this.observer = observer;
-            this.installerPackageName = installerPackageName;
+            this.installSource = Preconditions.checkNotNull(installSource);
             this.volumeUuid = volumeUuid;
             this.user = user;
             this.instructionSets = instructionSets;
@@ -14563,6 +14493,16 @@
             this.mMultiPackageInstallParams = multiPackageInstallParams;
         }
 
+        /** New install */
+        InstallArgs(InstallParams params) {
+            this(params.origin, params.move, params.observer, params.installFlags,
+                    params.installSource, params.volumeUuid,
+                    params.getUser(), null /*instructionSets*/, params.packageAbiOverride,
+                    params.grantedRuntimePermissions, params.whitelistedRestrictedPermissions,
+                    params.traceMethod, params.traceCookie, params.signingDetails,
+                    params.installReason, params.mParentInstallParams);
+        }
+
         abstract int copyApk();
         abstract int doPreInstall(int status);
 
@@ -14643,18 +14583,14 @@
 
         /** New install */
         FileInstallArgs(InstallParams params) {
-            super(params.origin, params.move, params.observer, params.installFlags,
-                    params.installerPackageName, params.volumeUuid,
-                    params.getUser(), null /*instructionSets*/, params.packageAbiOverride,
-                    params.grantedRuntimePermissions, params.whitelistedRestrictedPermissions,
-                    params.traceMethod, params.traceCookie, params.signingDetails,
-                    params.installReason, params.mParentInstallParams);
+            super(params);
         }
 
         /** Existing install */
         FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
-            super(OriginInfo.fromNothing(), null, null, 0, null, null, null, instructionSets,
-                    null, null, null, null, 0, PackageParser.SigningDetails.UNKNOWN,
+            super(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY,
+                    null, null, instructionSets, null, null, null, null, 0,
+                    PackageParser.SigningDetails.UNKNOWN,
                     PackageManager.INSTALL_REASON_UNKNOWN, null /* parent */);
             this.codeFile = (codePath != null) ? new File(codePath) : null;
             this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
@@ -14832,12 +14768,7 @@
 
         /** New install */
         MoveInstallArgs(InstallParams params) {
-            super(params.origin, params.move, params.observer, params.installFlags,
-                    params.installerPackageName, params.volumeUuid,
-                    params.getUser(), null /* instruction sets */, params.packageAbiOverride,
-                    params.grantedRuntimePermissions, params.whitelistedRestrictedPermissions,
-                    params.traceMethod, params.traceCookie, params.signingDetails,
-                    params.installReason, params.mParentInstallParams);
+            super(params);
         }
 
         int copyApk() {
@@ -15096,38 +15027,38 @@
         return disabled;
     }
 
-    private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
-            int[] allUsers, PackageInstalledInfo res, UserHandle user, int installReason) {
+    private void updateSettingsLI(PackageParser.Package newPackage,
+            InstallArgs installArgs, int[] allUsers, PackageInstalledInfo res) {
         // Update the parent package setting
-        updateSettingsInternalLI(newPackage, installerPackageName, allUsers, res.origUsers,
-                res, user, installReason);
+        updateSettingsInternalLI(newPackage, installArgs, allUsers, res);
         // Update the child packages setting
         final int childCount = (newPackage.childPackages != null)
                 ? newPackage.childPackages.size() : 0;
         for (int i = 0; i < childCount; i++) {
             PackageParser.Package childPackage = newPackage.childPackages.get(i);
             PackageInstalledInfo childRes = res.addedChildPackages.get(childPackage.packageName);
-            updateSettingsInternalLI(childPackage, installerPackageName, allUsers,
-                    childRes.origUsers, childRes, user, installReason);
+            updateSettingsInternalLI(childPackage, installArgs, allUsers, childRes);
         }
     }
 
     private void updateSettingsInternalLI(PackageParser.Package pkg,
-            String installerPackageName, int[] allUsers, int[] installedForUsers,
-            PackageInstalledInfo res, UserHandle user, int installReason) {
+            InstallArgs installArgs, int[] allUsers, PackageInstalledInfo res) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
 
         final String pkgName = pkg.packageName;
+        final String installerPackageName = installArgs.installSource.installerPackageName;
+        final int[] installedForUsers = res.origUsers;
+        final int installReason = installArgs.installReason;
 
         if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.codePath);
         synchronized (mLock) {
 // NOTE: This changes slightly to include UPDATE_PERMISSIONS_ALL regardless of the size of pkg.permissions
-            mPermissionManager.updatePermissions(pkg.packageName, pkg);
+            mPermissionManager.updatePermissions(pkgName, pkg);
             // For system-bundled packages, we assume that installing an upgraded version
             // of the package implies that the user actually wants to run that new code,
             // so we enable the package.
             PackageSetting ps = mSettings.mPackages.get(pkgName);
-            final int userId = user.getIdentifier();
+            final int userId = installArgs.user.getIdentifier();
             if (ps != null) {
                 if (isSystemApp(pkg)) {
                     if (DEBUG_INSTALL) {
@@ -15163,6 +15094,9 @@
                     ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, installerPackageName);
                 }
 
+                ps.setInstallSource(installArgs.installSource);
+
+
                 // When replacing an existing package, preserve the original install reason for all
                 // users that had the package installed before.
                 final Set<Integer> previousUserIds = new ArraySet<>();
@@ -15806,8 +15740,7 @@
             }
 
             commitReconciledScanResultLocked(reconciledPkg);
-            updateSettingsLI(pkg, reconciledPkg.installArgs.installerPackageName, request.mAllUsers,
-                    res, reconciledPkg.installArgs.user, reconciledPkg.installArgs.installReason);
+            updateSettingsLI(pkg, reconciledPkg.installArgs, request.mAllUsers, res);
 
             final PackageSetting ps = mSettings.mPackages.get(packageName);
             if (ps != null) {
@@ -15817,8 +15750,7 @@
             final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
             for (int i = 0; i < childCount; i++) {
                 PackageParser.Package childPkg = pkg.childPackages.get(i);
-                PackageInstalledInfo childRes = res.addedChildPackages.get(
-                        childPkg.packageName);
+                PackageInstalledInfo childRes = res.addedChildPackages.get(childPkg.packageName);
                 PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
                 if (childPs != null) {
                     childRes.newUsers = childPs.queryInstalledUsers(
@@ -15882,7 +15814,8 @@
                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                 }
                 request.installResult.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
-                request.installResult.installerPackageName = request.args.installerPackageName;
+                request.installResult.installerPackageName =
+                        request.args.installSource.installerPackageName;
 
                 final String packageName = prepareResult.packageToScan.packageName;
                 prepareResults.put(packageName, prepareResult);
@@ -16065,10 +15998,6 @@
      * will be used to scan and reconcile the package.
      */
     private static class PrepareResult {
-        public final int installReason;
-        public final String volumeUuid;
-        public final String installerPackageName;
-        public final UserHandle user;
         public final boolean replace;
         public final int scanFlags;
         public final int parseFlags;
@@ -16077,24 +16006,16 @@
         public final PackageParser.Package packageToScan;
         public final boolean clearCodeCache;
         public final boolean system;
-        /* The original package name if it was changed during an update, otherwise {@code null}. */
-        @Nullable
-        public final String renamedPackage;
         public final PackageFreezer freezer;
         public final PackageSetting originalPs;
         public final PackageSetting disabledPs;
         public final PackageSetting[] childPackageSettings;
 
-        private PrepareResult(int installReason, String volumeUuid,
-                String installerPackageName, UserHandle user, boolean replace, int scanFlags,
+        private PrepareResult(boolean replace, int scanFlags,
                 int parseFlags, PackageParser.Package existingPackage,
                 PackageParser.Package packageToScan, boolean clearCodeCache, boolean system,
-                String renamedPackage, PackageFreezer freezer, PackageSetting originalPs,
+                PackageFreezer freezer, PackageSetting originalPs,
                 PackageSetting disabledPs, PackageSetting[] childPackageSettings) {
-            this.installReason = installReason;
-            this.volumeUuid = volumeUuid;
-            this.installerPackageName = installerPackageName;
-            this.user = user;
             this.replace = replace;
             this.scanFlags = scanFlags;
             this.parseFlags = parseFlags;
@@ -16102,7 +16023,6 @@
             this.packageToScan = packageToScan;
             this.clearCodeCache = clearCodeCache;
             this.system = system;
-            this.renamedPackage = renamedPackage;
             this.freezer = freezer;
             this.originalPs = originalPs;
             this.disabledPs = disabledPs;
@@ -16142,8 +16062,6 @@
     private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
             throws PrepareFailure {
         final int installFlags = args.installFlags;
-        final String installerPackageName = args.installerPackageName;
-        final String volumeUuid = args.volumeUuid;
         final File tmpPackageFile = new File(args.getCodePath());
         final boolean onExternal = args.volumeUuid != null;
         final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
@@ -16243,7 +16161,8 @@
                     if ((mPackages.containsKey(childPkg.packageName))) {
                         childRes.removedInfo = new PackageRemovedInfo(this);
                         childRes.removedInfo.removedPackage = childPkg.packageName;
-                        childRes.removedInfo.installerPackageName = childPs.installerPackageName;
+                        childRes.removedInfo.installerPackageName =
+                                childPs.installSource.installerPackageName;
                     }
                     if (res.addedChildPackages == null) {
                         res.addedChildPackages = new ArrayMap<>();
@@ -16568,14 +16487,12 @@
             final PackageParser.Package existingPackage;
             String renamedPackage = null;
             boolean sysPkg = false;
-            String targetVolumeUuid = volumeUuid;
             int targetScanFlags = scanFlags;
             int targetParseFlags = parseFlags;
             final PackageSetting ps;
             final PackageSetting disabledPs;
             final PackageSetting[] childPackages;
             if (replace) {
-                targetVolumeUuid = null;
                 if (pkg.applicationInfo.isStaticSharedLibrary()) {
                     // Static libs have a synthetic package name containing the version
                     // and cannot be updated as an update would get a new package name,
@@ -16693,7 +16610,7 @@
                 res.removedInfo = new PackageRemovedInfo(this);
                 res.removedInfo.uid = oldPackage.applicationInfo.uid;
                 res.removedInfo.removedPackage = oldPackage.packageName;
-                res.removedInfo.installerPackageName = ps.installerPackageName;
+                res.removedInfo.installerPackageName = ps.installSource.installerPackageName;
                 res.removedInfo.isStaticSharedLib = pkg.staticSharedLibName != null;
                 res.removedInfo.isUpdate = true;
                 res.removedInfo.origUsers = installedUsers;
@@ -16716,7 +16633,7 @@
                                 childRes.removedInfo.removedPackage = childPkg.packageName;
                                 if (childPs != null) {
                                     childRes.removedInfo.installerPackageName =
-                                            childPs.installerPackageName;
+                                            childPs.installSource.installerPackageName;
                                 }
                                 childRes.removedInfo.isUpdate = true;
                                 childRes.removedInfo.installReasons =
@@ -16728,7 +16645,8 @@
                             PackageRemovedInfo childRemovedRes = new PackageRemovedInfo(this);
                             childRemovedRes.removedPackage = childPkg.packageName;
                             if (childPs != null) {
-                                childRemovedRes.installerPackageName = childPs.installerPackageName;
+                                childRemovedRes.installerPackageName =
+                                        childPs.installSource.installerPackageName;
                             }
                             childRemovedRes.isUpdate = false;
                             childRemovedRes.dataRemoved = true;
@@ -16827,9 +16745,8 @@
             // we're passing the freezer back to be closed in a later phase of install
             shouldCloseFreezerBeforeReturn = false;
 
-            return new PrepareResult(args.installReason, targetVolumeUuid, installerPackageName,
-                    args.user, replace, targetScanFlags, targetParseFlags, existingPackage, pkg,
-                    replace /* clearCodeCache */, sysPkg, renamedPackage, freezer,
+            return new PrepareResult(replace, targetScanFlags, targetParseFlags,
+                    existingPackage, pkg, replace /* clearCodeCache */, sysPkg, freezer,
                     ps, disabledPs, childPackages);
         } finally {
             if (shouldCloseFreezerBeforeReturn) {
@@ -17751,7 +17668,7 @@
         final PackageParser.Package deletedPkg = deletedPs.pkg;
         if (outInfo != null) {
             outInfo.removedPackage = packageName;
-            outInfo.installerPackageName = deletedPs.installerPackageName;
+            outInfo.installerPackageName = deletedPs.installSource.installerPackageName;
             outInfo.isStaticSharedLib = deletedPkg != null
                     && deletedPkg.staticSharedLibName != null;
             outInfo.populateUsers(deletedPs == null ? null
@@ -18346,7 +18263,7 @@
                     String childPackageName = ps.childPackageNames.get(i);
                     PackageRemovedInfo childInfo = new PackageRemovedInfo(this);
                     childInfo.removedPackage = childPackageName;
-                    childInfo.installerPackageName = ps.installerPackageName;
+                    childInfo.installerPackageName = ps.installSource.installerPackageName;
                     outInfo.removedChildPackages.put(childPackageName, childInfo);
                     PackageSetting childPs = mSettings.getPackageLPr(childPackageName);
                     if (childPs != null) {
@@ -18486,7 +18403,7 @@
 
         if (outInfo != null) {
             outInfo.removedPackage = ps.name;
-            outInfo.installerPackageName = ps.installerPackageName;
+            outInfo.installerPackageName = ps.installSource.installerPackageName;
             outInfo.isStaticSharedLib = pkg != null && pkg.staticSharedLibName != null;
             outInfo.removedAppId = ps.appId;
             outInfo.removedUsers = userIds;
@@ -19798,6 +19715,16 @@
     }
 
     @Override
+    public String[] getTelephonyPackageNames() {
+        String names = mContext.getString(R.string.config_telephonyPackages);
+        String[] telephonyPackageNames = null;
+        if (!TextUtils.isEmpty(names)) {
+            telephonyPackageNames = names.trim().split(",");
+        }
+        return telephonyPackageNames;
+    }
+
+    @Override
     public void setApplicationEnabledSetting(String appPackageName,
             int newState, int flags, int userId, String callingPackage) {
         if (!mUserManager.exists(userId)) return;
@@ -21941,7 +21868,7 @@
 
         final String currentVolumeUuid;
         final File codeFile;
-        final String installerPackageName;
+        final InstallSource installSource;
         final String packageAbiOverride;
         final int appId;
         final String seinfo;
@@ -21998,7 +21925,7 @@
 
             isCurrentLocationExternal = isExternal(pkg);
             codeFile = new File(pkg.codePath);
-            installerPackageName = ps.installerPackageName;
+            installSource = ps.installSource;
             packageAbiOverride = ps.cpuAbiOverrideString;
             appId = UserHandle.getAppId(pkg.applicationInfo.uid);
             seinfo = pkg.applicationInfo.seInfo;
@@ -22144,7 +22071,7 @@
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
         final InstallParams params = new InstallParams(origin, move, installObserver, installFlags,
-                installerPackageName, volumeUuid, null /*verificationInfo*/, user,
+                installSource, volumeUuid, null /*verificationInfo*/, user,
                 packageAbiOverride, null /*grantedPermissions*/,
                 null /*whitelistedRestrictedPermissions*/, PackageParser.SigningDetails.UNKNOWN,
                 PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.VERSION_CODE_HIGHEST);
@@ -22902,34 +22829,38 @@
         }
 
         @Override
-        public String getKnownPackageName(int knownPackage, int userId) {
+        public @NonNull String[] getKnownPackageNames(int knownPackage, int userId) {
             switch(knownPackage) {
                 case PackageManagerInternal.PACKAGE_BROWSER:
-                    return mPermissionManager.getDefaultBrowser(userId);
+                    return new String[]{mPermissionManager.getDefaultBrowser(userId)};
                 case PackageManagerInternal.PACKAGE_INSTALLER:
-                    return mRequiredInstallerPackage;
+                    return new String[]{mRequiredInstallerPackage};
                 case PackageManagerInternal.PACKAGE_SETUP_WIZARD:
-                    return mSetupWizardPackage;
+                    return new String[]{mSetupWizardPackage};
                 case PackageManagerInternal.PACKAGE_SYSTEM:
-                    return "android";
+                    return new String[]{"android"};
                 case PackageManagerInternal.PACKAGE_VERIFIER:
-                    return mRequiredVerifierPackage;
+                    return new String[]{mRequiredVerifierPackage};
                 case PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER:
-                    return mSystemTextClassifierPackage;
+                    return new String[]{mSystemTextClassifierPackage};
                 case PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER:
-                    return mRequiredPermissionControllerPackage;
+                    return new String[]{mRequiredPermissionControllerPackage};
                 case PackageManagerInternal.PACKAGE_WELLBEING:
-                    return mWellbeingPackage;
+                    return new String[]{mWellbeingPackage};
                 case PackageManagerInternal.PACKAGE_DOCUMENTER:
-                    return mDocumenterPackage;
+                    return new String[]{mDocumenterPackage};
                 case PackageManagerInternal.PACKAGE_CONFIGURATOR:
-                    return mConfiguratorPackage;
+                    return new String[]{mConfiguratorPackage};
                 case PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER:
-                    return mIncidentReportApproverPackage;
+                    return new String[]{mIncidentReportApproverPackage};
                 case PackageManagerInternal.PACKAGE_APP_PREDICTOR:
-                    return mAppPredictionServicePackage;
+                    return new String[]{mAppPredictionServicePackage};
+                case PackageManagerInternal.PACKAGE_TELEPHONY:
+                    return mTelephonyPackages;
+                case PackageManagerInternal.PACKAGE_WIFI:
+                    return new String[]{mWifiPackage};
             }
-            return null;
+            return ArrayUtils.emptyArray(String.class);
         }
 
         @Override
@@ -23602,7 +23533,7 @@
                     return false;
                 }
                 final PackageSetting installerPackageSetting =
-                        mSettings.mPackages.get(packageSetting.installerPackageName);
+                        mSettings.mPackages.get(packageSetting.installSource.installerPackageName);
                 return installerPackageSetting != null
                         && UserHandle.isSameApp(installerPackageSetting.appId, callingUid);
             }
@@ -24025,20 +23956,20 @@
         private final File mStagedDir;
         private final IPackageInstallObserver2 mObserver;
         private final PackageInstaller.SessionParams mSessionParams;
-        private final String mInstallerPackageName;
         private final int mInstallerUid;
+        @NonNull private final InstallSource mInstallSource;
         private final UserHandle mUser;
         private final SigningDetails mSigningDetails;
 
         ActiveInstallSession(String packageName, File stagedDir, IPackageInstallObserver2 observer,
-                PackageInstaller.SessionParams sessionParams, String installerPackageName,
-                int installerUid, UserHandle user, SigningDetails signingDetails) {
+                PackageInstaller.SessionParams sessionParams, int installerUid,
+                InstallSource installSource, UserHandle user, SigningDetails signingDetails) {
             mPackageName = packageName;
             mStagedDir = stagedDir;
             mObserver = observer;
             mSessionParams = sessionParams;
-            mInstallerPackageName = installerPackageName;
             mInstallerUid = installerUid;
+            mInstallSource = Preconditions.checkNotNull(installSource);
             mUser = user;
             mSigningDetails = signingDetails;
         }
@@ -24059,14 +23990,15 @@
             return mSessionParams;
         }
 
-        public String getInstallerPackageName() {
-            return mInstallerPackageName;
-        }
-
         public int getInstallerUid() {
             return mInstallerUid;
         }
 
+        @NonNull
+        public InstallSource getInstallSource() {
+            return mInstallSource;
+        }
+
         public UserHandle getUser() {
             return mUser;
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 1c1c947..f1c84b8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -468,7 +468,7 @@
      * @param pckg
      */
     private int displayPackageFilePath(String pckg, int userId) throws RemoteException {
-        PackageInfo info = mInterface.getPackageInfo(pckg, 0, userId);
+        PackageInfo info = mInterface.getPackageInfo(pckg, PackageManager.MATCH_APEX, userId);
         if (info != null && info.applicationInfo != null) {
             final PrintWriter pw = getOutPrintWriter();
             pw.print("package:");
@@ -2437,10 +2437,14 @@
             }
         }
         String arg = getNextArg();
-        if (arg == null) {
+        if (arg == null && !preCreateOnly) {
             getErrPrintWriter().println("Error: no user name specified.");
             return 1;
         }
+        if (arg != null && preCreateOnly) {
+            getErrPrintWriter().println("Warning: name is ignored for pre-created users");
+        }
+
         name = arg;
         UserInfo info;
         IUserManager um = IUserManager.Stub.asInterface(
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 4ea8a30..4fca91a 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -187,7 +187,7 @@
         proto.write(PackageProto.VERSION_CODE, versionCode);
         proto.write(PackageProto.INSTALL_TIME_MS, firstInstallTime);
         proto.write(PackageProto.UPDATE_TIME_MS, lastUpdateTime);
-        proto.write(PackageProto.INSTALLER_NAME, installerPackageName);
+        proto.write(PackageProto.INSTALLER_NAME, installSource.installerPackageName);
 
         if (pkg != null) {
             proto.write(PackageProto.VERSION_STRING, pkg.mVersionName);
@@ -205,6 +205,11 @@
                     proto.end(splitToken);
                 }
             }
+
+            long sourceToken = proto.start(PackageProto.INSTALL_SOURCE);
+            proto.write(PackageProto.InstallSourceProto.INITIATING_PACKAGE_NAME,
+                    installSource.initiatingPackageName);
+            proto.end(sourceToken);
         }
         writeUsersInfoToProto(proto, PackageProto.USERS);
         proto.end(packageToken);
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 0da6b54..45ab357 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -20,6 +20,7 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 
+import android.annotation.NonNull;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.PackageManager;
@@ -35,6 +36,7 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -121,10 +123,8 @@
      */
     Set<String> mOldCodePaths;
 
-    /** Package name of the app that installed this package */
-    String installerPackageName;
-    /** Indicates if the package that installed this app has been uninstalled */
-    boolean isOrphaned;
+    /** Information about how this package was installed/updated. */
+    @NonNull InstallSource installSource;
     /** UUID of {@link VolumeInfo} hosting this app */
     String volumeUuid;
     /** The category of this app, as hinted by the installer */
@@ -148,8 +148,17 @@
                 ? new ArrayList<>(childPackageNames) : null;
         this.usesStaticLibraries = usesStaticLibraries;
         this.usesStaticLibrariesVersions = usesStaticLibrariesVersions;
-        init(codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbiString,
-                secondaryCpuAbiString, cpuAbiOverrideString, pVersionCode);
+        this.codePath = codePath;
+        this.codePathString = codePath.toString();
+        this.resourcePath = resourcePath;
+        this.resourcePathString = resourcePath.toString();
+        this.legacyNativeLibraryPathString = legacyNativeLibraryPathString;
+        this.primaryCpuAbiString = primaryCpuAbiString;
+        this.secondaryCpuAbiString = secondaryCpuAbiString;
+        this.cpuAbiOverrideString = cpuAbiOverrideString;
+        this.versionCode = pVersionCode;
+        this.signatures = new PackageSignatures();
+        this.installSource = InstallSource.EMPTY;
     }
 
     /**
@@ -166,27 +175,20 @@
         doCopy(base);
     }
 
-    void init(File codePath, File resourcePath, String legacyNativeLibraryPathString,
-              String primaryCpuAbiString, String secondaryCpuAbiString,
-              String cpuAbiOverrideString, long pVersionCode) {
-        this.codePath = codePath;
-        this.codePathString = codePath.toString();
-        this.resourcePath = resourcePath;
-        this.resourcePathString = resourcePath.toString();
-        this.legacyNativeLibraryPathString = legacyNativeLibraryPathString;
-        this.primaryCpuAbiString = primaryCpuAbiString;
-        this.secondaryCpuAbiString = secondaryCpuAbiString;
-        this.cpuAbiOverrideString = cpuAbiOverrideString;
-        this.versionCode = pVersionCode;
-        this.signatures = new PackageSignatures();
-    }
-
     public void setInstallerPackageName(String packageName) {
-        installerPackageName = packageName;
+        installSource = installSource.setInstallerPackage(packageName);
     }
 
-    public String getInstallerPackageName() {
-        return installerPackageName;
+    public void setInstallSource(InstallSource installSource) {
+        this.installSource = Preconditions.checkNotNull(installSource);
+    }
+
+    void removeInstallerPackage(String packageName) {
+        installSource = installSource.removeInstallerPackage(packageName);
+    }
+
+    public void setIsOrphaned(boolean isOrphaned) {
+        installSource = installSource.setIsOrphaned(isOrphaned);
     }
 
     public void setVolumeUuid(String volumeUuid) {
@@ -240,8 +242,7 @@
         cpuAbiOverrideString = orig.cpuAbiOverrideString;
         firstInstallTime = orig.firstInstallTime;
         installPermissionsFixed = orig.installPermissionsFixed;
-        installerPackageName = orig.installerPackageName;
-        isOrphaned = orig.isOrphaned;
+        installSource = orig.installSource;
         keySetData = orig.keySetData;
         lastUpdateTime = orig.lastUpdateTime;
         legacyNativeLibraryPathString = orig.legacyNativeLibraryPathString;
@@ -689,8 +690,7 @@
         this.signatures = other.signatures;
         this.installPermissionsFixed = other.installPermissionsFixed;
         this.keySetData = other.keySetData;
-        this.installerPackageName = other.installerPackageName;
-        this.isOrphaned = other.isOrphaned;
+        this.installSource = other.installSource;
         this.volumeUuid = other.volumeUuid;
         this.categoryHint = other.categoryHint;
         this.updateAvailable = other.updateAvailable;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 0db6e79..a11ae8c 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -554,10 +554,6 @@
         return null;
     }
 
-    void addAppOpPackage(String permName, String packageName) {
-        mPermissions.addAppOpPackage(permName, packageName);
-    }
-
     SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
         SharedUserSetting s = mSharedUsers.get(name);
         if (s != null) {
@@ -1052,13 +1048,7 @@
             return;
         }
         for (int i = 0; i < mPackages.size(); i++) {
-            final PackageSetting ps = mPackages.valueAt(i);
-            final String installerPackageName = ps.getInstallerPackageName();
-            if (installerPackageName != null
-                    && installerPackageName.equals(packageName)) {
-                ps.setInstallerPackageName(null);
-                ps.isOrphaned = true;
-            }
+            mPackages.valueAt(i).removeInstallerPackage(packageName);
         }
         mInstallerPackages.remove(packageName);
     }
@@ -2848,18 +2838,21 @@
         if (pkg.uidError) {
             serializer.attribute(null, "uidError", "true");
         }
-        if (pkg.installerPackageName != null) {
-            serializer.attribute(null, "installer", pkg.installerPackageName);
+        InstallSource installSource = pkg.installSource;
+        if (installSource.installerPackageName != null) {
+            serializer.attribute(null, "installer", installSource.installerPackageName);
         }
-        if (pkg.isOrphaned) {
+        if (installSource.isOrphaned) {
             serializer.attribute(null, "isOrphaned", "true");
         }
+        if (installSource.initiatingPackageName != null) {
+            serializer.attribute(null, "installInitiator", installSource.initiatingPackageName);
+        }
         if (pkg.volumeUuid != null) {
             serializer.attribute(null, "volumeUuid", pkg.volumeUuid);
         }
         if (pkg.categoryHint != ApplicationInfo.CATEGORY_UNDEFINED) {
-            serializer.attribute(null, "categoryHint",
-                    Integer.toString(pkg.categoryHint));
+            serializer.attribute(null, "categoryHint", Integer.toString(pkg.categoryHint));
         }
         if (pkg.parentPackageName != null) {
             serializer.attribute(null, "parentPackageName", pkg.parentPackageName);
@@ -2874,8 +2867,7 @@
 
         pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
 
-        writePermissionsLPr(serializer, pkg.getPermissionsState()
-                    .getInstallPermissionStates());
+        writePermissionsLPr(serializer, pkg.getPermissionsState().getInstallPermissionStates());
 
         writeSigningKeySetLPr(serializer, pkg.keySetData);
         writeUpgradeKeySetsLPr(serializer, pkg.keySetData);
@@ -3613,6 +3605,7 @@
         String systemStr = null;
         String installerPackageName = null;
         String isOrphaned = null;
+        String installInitiatingPackageName = null;
         String volumeUuid = null;
         String categoryHintString = null;
         String updateAvailable = null;
@@ -3659,6 +3652,7 @@
             }
             installerPackageName = parser.getAttributeValue(null, "installer");
             isOrphaned = parser.getAttributeValue(null, "isOrphaned");
+            installInitiatingPackageName = parser.getAttributeValue(null, "installInitiator");
             volumeUuid = parser.getAttributeValue(null, "volumeUuid");
             categoryHintString = parser.getAttributeValue(null, "categoryHint");
             if (categoryHintString != null) {
@@ -3813,8 +3807,8 @@
         }
         if (packageSetting != null) {
             packageSetting.uidError = "true".equals(uidError);
-            packageSetting.installerPackageName = installerPackageName;
-            packageSetting.isOrphaned = "true".equals(isOrphaned);
+            packageSetting.installSource = InstallSource.create(
+                    installInitiatingPackageName, installerPackageName, "true".equals(isOrphaned));
             packageSetting.volumeUuid = volumeUuid;
             packageSetting.categoryHint = categoryHint;
             packageSetting.legacyNativeLibraryPathString = legacyNativeLibraryPathStr;
@@ -4257,7 +4251,7 @@
         if (pkg == null) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
-        return pkg.installerPackageName;
+        return pkg.installSource.installerPackageName;
     }
 
     boolean isOrphaned(String packageName) {
@@ -4265,7 +4259,7 @@
         if (pkg == null) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
-        return pkg.isOrphaned;
+        return pkg.installSource.isOrphaned;
     }
 
     int getApplicationEnabledSettingLPr(String packageName, int userId) {
@@ -4318,8 +4312,9 @@
             pkgSetting.setStopped(stopped, userId);
             // pkgSetting.pkg.mSetStopped = stopped;
             if (pkgSetting.getNotLaunched(userId)) {
-                if (pkgSetting.installerPackageName != null) {
-                    pm.notifyFirstLaunch(pkgSetting.name, pkgSetting.installerPackageName, userId);
+                if (pkgSetting.installSource.installerPackageName != null) {
+                    pm.notifyFirstLaunch(pkgSetting.name,
+                            pkgSetting.installSource.installerPackageName, userId);
                 }
                 pkgSetting.setNotLaunched(false, userId);
             }
@@ -4482,7 +4477,8 @@
             pw.print(",");
             pw.print(ps.lastUpdateTime);
             pw.print(",");
-            pw.print(ps.installerPackageName != null ? ps.installerPackageName : "?");
+            pw.print(ps.installSource.installerPackageName != null
+                    ? ps.installSource.installerPackageName : "?");
             pw.println();
             if (ps.pkg != null) {
                 pw.print(checkinTag); pw.print("-"); pw.print("splt,");
@@ -4695,9 +4691,9 @@
         pw.print(prefix); pw.print("  lastUpdateTime=");
             date.setTime(ps.lastUpdateTime);
             pw.println(sdf.format(date));
-        if (ps.installerPackageName != null) {
+        if (ps.installSource.installerPackageName != null) {
             pw.print(prefix); pw.print("  installerPackageName=");
-                    pw.println(ps.installerPackageName);
+            pw.println(ps.installSource.installerPackageName);
         }
         if (ps.volumeUuid != null) {
             pw.print(prefix); pw.print("  volumeUuid=");
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 95baa01..22eb1b497 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2846,7 +2846,7 @@
                     return null;
                 }
                 // If we're adding a guest and there already exists one, bail.
-                if (isGuest && findCurrentGuestUser() != null) {
+                if (isGuest && !preCreate && findCurrentGuestUser() != null) {
                     Log.e(LOG_TAG, "Cannot add guest user. Guest user already exists.");
                     return null;
                 }
@@ -3100,7 +3100,8 @@
             final int size = mUsers.size();
             for (int i = 0; i < size; i++) {
                 final UserInfo user = mUsers.valueAt(i).info;
-                if (user.isGuest() && !user.guestToRemove && !mRemovingUserIds.get(user.id)) {
+                if (user.isGuest() && !user.guestToRemove && !user.preCreated
+                        && !mRemovingUserIds.get(user.id)) {
                     return user;
                 }
             }
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index 6d22faa..037912a 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -276,6 +276,12 @@
     public boolean isAppPredictor() {
         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0;
     }
+    public boolean isTelephony() {
+        return (protectionLevel & PermissionInfo.PROTECTION_FLAG_TELEPHONY) != 0;
+    }
+    public boolean isWifi() {
+        return (protectionLevel & PermissionInfo.PROTECTION_FLAG_WIFI) != 0;
+    }
 
     public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) {
         if (!origPackageName.equals(sourcePackageName)) {
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 793cdd2..f247037 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -437,17 +437,20 @@
 
         // Installer
         grantSystemFixedPermissionsToSystemPackage(
-                getKnownPackage(PackageManagerInternal.PACKAGE_INSTALLER, userId),
+                ArrayUtils.firstOrNull(getKnownPackages(
+                        PackageManagerInternal.PACKAGE_INSTALLER, userId)),
                 userId, STORAGE_PERMISSIONS);
 
         // Verifier
-        final String verifier = getKnownPackage(PackageManagerInternal.PACKAGE_VERIFIER, userId);
+        final String verifier = ArrayUtils.firstOrNull(getKnownPackages(
+                PackageManagerInternal.PACKAGE_VERIFIER, userId));
         grantSystemFixedPermissionsToSystemPackage(verifier, userId, STORAGE_PERMISSIONS);
         grantPermissionsToSystemPackage(verifier, userId, PHONE_PERMISSIONS, SMS_PERMISSIONS);
 
         // SetupWizard
         grantPermissionsToSystemPackage(
-                getKnownPackage(PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId), userId,
+                ArrayUtils.firstOrNull(getKnownPackages(
+                        PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId)), userId,
                 PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS,
                 CAMERA_PERMISSIONS);
 
@@ -596,7 +599,8 @@
                 userId, CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS);
 
         // Browser
-        String browserPackage = getKnownPackage(PackageManagerInternal.PACKAGE_BROWSER, userId);
+        String browserPackage = ArrayUtils.firstOrNull(getKnownPackages(
+                PackageManagerInternal.PACKAGE_BROWSER, userId));
         if (browserPackage == null) {
             browserPackage = getDefaultSystemHandlerActivityPackageForCategory(
                     Intent.CATEGORY_APP_BROWSER, userId);
@@ -761,8 +765,8 @@
         }
     }
 
-    private String getKnownPackage(int knownPkgId, int userId) {
-        return mServiceInternal.getKnownPackageName(knownPkgId, userId);
+    private @NonNull String[] getKnownPackages(int knownPkgId, int userId) {
+        return mServiceInternal.getKnownPackageNames(knownPkgId, userId);
     }
 
     private void grantDefaultPermissionsToDefaultSystemDialerApp(
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 89908f0..9e88d0c 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -53,6 +53,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
+import android.app.AppOpsManager;
 import android.app.ApplicationPackageManager;
 import android.app.IActivityManager;
 import android.content.Context;
@@ -297,7 +298,7 @@
             // Critical; after this call the application should never have the permission
             mPackageManagerInt.writeSettings(false);
             final int appId = UserHandle.getAppId(uid);
-            killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
+            mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED));
         }
         @Override
         public void onInstallPermissionRevoked() {
@@ -1541,6 +1542,7 @@
             }
         };
 
+        final AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
         for (int i = 0; i < permissionCount; i++) {
             final String permName = pkg.requestedPermissions.get(i);
             final BasePermission bp;
@@ -1606,9 +1608,16 @@
 
             // If this permission was granted by default, make sure it is.
             if ((oldFlags & FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0) {
-                // PermissionPolicyService will handle the app op for runtime permissions later.
                 grantRuntimePermissionInternal(permName, packageName, false,
                         Process.SYSTEM_UID, userId, delayingPermCallback);
+                // Allow app op later as we are holding mPackages
+                // PermissionPolicyService will handle the app op for foreground/background
+                // permissions.
+                String appOp = AppOpsManager.permissionToOp(permName);
+                if (appOp != null) {
+                    mHandler.post(() -> appOpsManager.setUidMode(appOp, uid,
+                            AppOpsManager.MODE_ALLOWED));
+                }
             // If permission review is enabled the permissions for a legacy apps
             // are represented as constantly granted runtime ones, so don't revoke.
             } else if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
@@ -1902,7 +1911,7 @@
     private void restoreRuntimePermissions(@NonNull byte[] backup, @NonNull UserHandle user) {
         synchronized (mLock) {
             mHasNoDelayedPermBackup.delete(user.getIdentifier());
-            mPermissionControllerManager.restoreRuntimePermissionBackup(backup, user);
+            mPermissionControllerManager.stageAndApplyRuntimePermissionsBackup(backup, user);
         }
     }
 
@@ -1923,7 +1932,7 @@
                 return;
             }
 
-            mPermissionControllerManager.restoreDelayedRuntimePermissionBackup(packageName, user,
+            mPermissionControllerManager.applyStagedRuntimePermissionBackup(packageName, user,
                     mContext.getMainExecutor(), (hasMoreBackup) -> {
                         if (hasMoreBackup) {
                             return;
@@ -3078,8 +3087,9 @@
                 }
             }
         }
-        final String systemPackageName = mPackageManagerInt.getKnownPackageName(
-                PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM);
+        // expect single system package
+        String systemPackageName = ArrayUtils.firstOrNull(mPackageManagerInt.getKnownPackageNames(
+                PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM));
         final PackageParser.Package systemPackage =
                 mPackageManagerInt.getPackage(systemPackageName);
 
@@ -3195,18 +3205,19 @@
             //                  need a separate flag anymore. Hence we need to check which
             //                  permissions are needed by the permission controller
             if (!allowed && bp.isInstaller()
-                    && (pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
-                            PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM))
-                    || pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
+                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
+                            PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM),
+                    pkg.packageName) || ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
                             PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER,
-                            UserHandle.USER_SYSTEM)))) {
+                    UserHandle.USER_SYSTEM), pkg.packageName)) {
                 // If this permission is to be granted to the system installer and
                 // this app is an installer, then it gets the permission.
                 allowed = true;
             }
             if (!allowed && bp.isVerifier()
-                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
-                            PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM))) {
+                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
+                            PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM),
+                    pkg.packageName)) {
                 // If this permission is to be granted to the system verifier and
                 // this app is a verifier, then it gets the permission.
                 allowed = true;
@@ -3222,53 +3233,71 @@
                 allowed = origPermissions.hasInstallPermission(perm);
             }
             if (!allowed && bp.isSetup()
-                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
-                            PackageManagerInternal.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM))) {
+                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
+                            PackageManagerInternal.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM),
+                    pkg.packageName)) {
                 // If this permission is to be granted to the system setup wizard and
                 // this app is a setup wizard, then it gets the permission.
                 allowed = true;
             }
             if (!allowed && bp.isSystemTextClassifier()
-                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
+                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
                             PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER,
-                            UserHandle.USER_SYSTEM))) {
+                    UserHandle.USER_SYSTEM), pkg.packageName)) {
                 // Special permissions for the system default text classifier.
                 allowed = true;
             }
             if (!allowed && bp.isConfigurator()
-                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
-                    PackageManagerInternal.PACKAGE_CONFIGURATOR,
-                    UserHandle.USER_SYSTEM))) {
+                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
+                            PackageManagerInternal.PACKAGE_CONFIGURATOR,
+                    UserHandle.USER_SYSTEM), pkg.packageName)) {
                 // Special permissions for the device configurator.
                 allowed = true;
             }
             if (!allowed && bp.isWellbeing()
-                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
-                    PackageManagerInternal.PACKAGE_WELLBEING, UserHandle.USER_SYSTEM))) {
+                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
+                            PackageManagerInternal.PACKAGE_WELLBEING, UserHandle.USER_SYSTEM),
+                    pkg.packageName)) {
                 // Special permission granted only to the OEM specified wellbeing app
                 allowed = true;
             }
             if (!allowed && bp.isDocumenter()
-                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
-                            PackageManagerInternal.PACKAGE_DOCUMENTER, UserHandle.USER_SYSTEM))) {
+                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
+                            PackageManagerInternal.PACKAGE_DOCUMENTER, UserHandle.USER_SYSTEM),
+                    pkg.packageName)) {
                 // If this permission is to be granted to the documenter and
                 // this app is the documenter, then it gets the permission.
                 allowed = true;
             }
             if (!allowed && bp.isIncidentReportApprover()
-                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
+                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
                             PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER,
-                            UserHandle.USER_SYSTEM))) {
+                    UserHandle.USER_SYSTEM), pkg.packageName)) {
                 // 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.
                 allowed = true;
             }
             if (!allowed && bp.isAppPredictor()
-                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
-                        PackageManagerInternal.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM))) {
+                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
+                            PackageManagerInternal.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM),
+                    pkg.packageName)) {
                 // Special permissions for the system app predictor.
                 allowed = true;
             }
+            if (!allowed && bp.isTelephony()
+                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
+                        PackageManagerInternal.PACKAGE_TELEPHONY, UserHandle.USER_SYSTEM),
+                    pkg.packageName)) {
+                // Special permissions for the system telephony apps.
+                allowed = true;
+            }
+            if (!allowed && bp.isWifi()
+                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
+                        PackageManagerInternal.PACKAGE_WIFI, UserHandle.USER_SYSTEM),
+                    pkg.packageName)) {
+                // Special permissions for the system wifi.
+                allowed = true;
+            }
         }
         return allowed;
     }
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index df2b3ca..b892360 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -152,7 +152,7 @@
             for (int i = 0; i < numDangerousPerms; i++) {
                 PermissionInfo perm = dangerousPerms.get(i);
 
-                if (perm.isRuntime()) {
+                if (perm.isRestricted() || perm.backgroundPermission != null) {
                     appOpsService.startWatchingMode(getSwitchOp(perm.name), null, appOpsListener);
                 }
                 if (perm.isSoftRestricted()) {
@@ -499,7 +499,8 @@
 
         private void addPermissionAppOp(@NonNull PackageInfo packageInfo,
                 @NonNull PermissionInfo permissionInfo) {
-            if (!permissionInfo.isRuntime()) {
+            // TODO: Sync all permissions in the future.
+            if (!permissionInfo.isRestricted() && permissionInfo.backgroundPermission == null) {
                 return;
             }
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c851cc6..2593c38 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -47,8 +47,8 @@
 import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -2189,10 +2189,10 @@
             default:
                 // These are the windows that by default are shown only to the user that created
                 // them. If this needs to be overridden, set
-                // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in
+                // {@link WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS} in
                 // {@link WindowManager.LayoutParams}. Note that permission
                 // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well.
-                if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) {
+                if ((attrs.privateFlags & SYSTEM_FLAG_SHOW_FOR_ALL_USERS) == 0) {
                     return true;
                 }
                 break;
@@ -2446,7 +2446,7 @@
                     com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
             params.privateFlags |=
                     WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
-            params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+            params.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
 
             if (!compatInfo.supportsScreen()) {
                 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index eb648b3..befe4e9 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -548,12 +548,16 @@
 
     private final class ForegroundProfileObserver extends SynchronousUserSwitchObserver {
         @Override
-        public void onUserSwitching(int newUserId) throws RemoteException {}
+        public void onUserSwitching(@UserIdInt int newUserId) throws RemoteException {
+            synchronized (mLock) {
+                mUserId = newUserId;
+            }
+        }
 
         @Override
         public void onForegroundProfileSwitch(@UserIdInt int newProfileId) throws RemoteException {
             final long now = SystemClock.uptimeMillis();
-            synchronized(mLock) {
+            synchronized (mLock) {
                 mForegroundProfile = newProfileId;
                 maybeUpdateForegroundProfileLastActivityLocked(now);
             }
@@ -562,6 +566,8 @@
 
     // User id corresponding to activity the user is currently interacting with.
     private @UserIdInt int mForegroundProfile;
+    // User id of main profile for the current user (doesn't include managed profiles)
+    private @UserIdInt int mUserId;
 
     // Per-profile state to track when a profile should be locked.
     private final SparseArray<ProfilePowerState> mProfilePowerState = new SparseArray<>();
@@ -1792,9 +1798,9 @@
                 if (mBootCompleted) {
                     if (mIsPowered && !BatteryManager.isPlugWired(oldPlugType)
                             && BatteryManager.isPlugWired(mPlugType)) {
-                        mNotifier.onWiredChargingStarted(mForegroundProfile);
+                        mNotifier.onWiredChargingStarted(mUserId);
                     } else if (dockedOnWirelessCharger) {
-                        mNotifier.onWirelessChargingStarted(mBatteryLevel, mForegroundProfile);
+                        mNotifier.onWirelessChargingStarted(mBatteryLevel, mUserId);
                     }
                 }
             }
@@ -3493,6 +3499,7 @@
             pw.println("  mDoubleTapWakeEnabled=" + mDoubleTapWakeEnabled);
             pw.println("  mIsVrModeEnabled=" + mIsVrModeEnabled);
             pw.println("  mForegroundProfile=" + mForegroundProfile);
+            pw.println("  mUserId=" + mUserId);
 
             final long sleepTimeout = getSleepTimeoutLocked();
             final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index 1cf07cb..8b79c3f 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -21,6 +21,7 @@
 import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -33,7 +34,9 @@
 import android.content.rollback.RollbackManager;
 import android.os.Binder;
 import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
 import android.os.UserManager;
+import android.text.TextUtils;
 import android.util.IntArray;
 import android.util.Slog;
 import android.util.SparseLongArray;
@@ -142,18 +145,37 @@
     private final Object mLock = new Object();
 
     /**
+     * The user that performed the install with rollback enabled.
+     */
+    public final int mUserId;
+
+    /**
+     * The installer package name from the install session that enabled the rollback. May be null if
+     * that session did not set this value.
+     *
+     * If this is an empty string then the installer package name will be resolved by
+     * PackageManager.
+     */
+    @Nullable public final String mInstallerPackageName;
+
+    /**
      * Constructs a new, empty Rollback instance.
      *
      * @param rollbackId the id of the rollback.
      * @param backupDir the directory where the rollback data is stored.
      * @param stagedSessionId the session id if this is a staged rollback, -1 otherwise.
+     * @param userId the user that performed the install with rollback enabled.
+     * @param installerPackageName the installer package name from the original install session.
      */
-    Rollback(int rollbackId, File backupDir, int stagedSessionId) {
+    Rollback(int rollbackId, File backupDir, int stagedSessionId, int userId,
+            String installerPackageName) {
         this.info = new RollbackInfo(rollbackId,
                 /* packages */ new ArrayList<>(),
                 /* isStaged */ stagedSessionId != -1,
                 /* causePackages */ new ArrayList<>(),
                 /* committedSessionId */ -1);
+        mUserId = userId;
+        mInstallerPackageName = installerPackageName;
         mBackupDir = backupDir;
         mStagedSessionId = stagedSessionId;
         mState = ROLLBACK_STATE_ENABLING;
@@ -164,8 +186,11 @@
      * Constructs a pre-populated Rollback instance.
      */
     Rollback(RollbackInfo info, File backupDir, Instant timestamp, int stagedSessionId,
-            @RollbackState int state, int apkSessionId, boolean restoreUserDataInProgress) {
+            @RollbackState int state, int apkSessionId, boolean restoreUserDataInProgress,
+            int userId, String installerPackageName) {
         this.info = info;
+        mUserId = userId;
+        mInstallerPackageName = installerPackageName;
         mBackupDir = backupDir;
         mTimestamp = timestamp;
         mStagedSessionId = stagedSessionId;
@@ -216,6 +241,21 @@
     }
 
     /**
+     * Returns the ID of the user that performed the install with rollback enabled.
+     */
+    int getUserId() {
+        return mUserId;
+    }
+
+    /**
+     * Returns the installer package name from the install session that enabled the rollback. In the
+     * case that this is called on a rollback from an older version, returns the empty string.
+     */
+    @Nullable String getInstallerPackageName() {
+        return mInstallerPackageName;
+    }
+
+    /**
      * Returns true if the rollback is in the ENABLING state.
      */
     boolean isEnabling() {
@@ -360,7 +400,8 @@
             // Get a context to use to install the downgraded version of the package.
             Context pkgContext;
             try {
-                pkgContext = context.createPackageContext(callerPackageName, 0);
+                pkgContext = context.createPackageContextAsUser(callerPackageName, 0,
+                        UserHandle.of(mUserId));
             } catch (PackageManager.NameNotFoundException e) {
                 sendFailure(context, statusReceiver, RollbackManager.STATUS_FAILURE,
                         "Invalid callerPackageName");
@@ -385,15 +426,13 @@
                 for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) {
                     PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                             PackageInstaller.SessionParams.MODE_FULL_INSTALL);
-                    // TODO: We can't get the installerPackageName for apex
-                    // (b/123920130). Is it okay to ignore the installer package
-                    // for apex?
-                    if (!pkgRollbackInfo.isApex()) {
-                        String installerPackageName =
-                                pm.getInstallerPackageName(pkgRollbackInfo.getPackageName());
-                        if (installerPackageName != null) {
-                            params.setInstallerPackageName(installerPackageName);
-                        }
+                    String installerPackageName = mInstallerPackageName;
+                    if (TextUtils.isEmpty(mInstallerPackageName)) {
+                        installerPackageName = pm.getInstallerPackageName(
+                                pkgRollbackInfo.getPackageName());
+                    }
+                    if (installerPackageName != null) {
+                        params.setInstallerPackageName(installerPackageName);
                     }
                     params.setRequestDowngrade(true);
                     params.setRequiredInstalledVersionCode(
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index cd44f64..ef4c12e 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -1248,13 +1248,22 @@
     @GuardedBy("mLock")
     private NewRollback createNewRollbackLocked(PackageInstaller.SessionInfo parentSession) {
         int rollbackId = allocateRollbackIdLocked();
+        final int userId;
+        if (parentSession.getUser() == UserHandle.ALL) {
+            userId = UserHandle.USER_SYSTEM;
+        } else {
+            userId = parentSession.getUser().getIdentifier();
+        }
+        String installerPackageName = parentSession.getInstallerPackageName();
         final Rollback rollback;
         int parentSessionId = parentSession.getSessionId();
 
         if (parentSession.isStaged()) {
-            rollback = mRollbackStore.createStagedRollback(rollbackId, parentSessionId);
+            rollback = mRollbackStore.createStagedRollback(rollbackId, parentSessionId, userId,
+                    installerPackageName);
         } else {
-            rollback = mRollbackStore.createNonStagedRollback(rollbackId);
+            rollback = mRollbackStore.createNonStagedRollback(rollbackId, userId,
+                    installerPackageName);
         }
 
         int[] packageSessionIds;
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 425da37..550c754 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -16,6 +16,8 @@
 
 package com.android.server.rollback;
 
+import static android.os.UserHandle.USER_SYSTEM;
+
 import static com.android.server.rollback.Rollback.rollbackStateFromString;
 
 import android.annotation.NonNull;
@@ -196,18 +198,19 @@
      * Creates a new Rollback instance for a non-staged rollback with
      * backupDir assigned.
      */
-    Rollback createNonStagedRollback(int rollbackId) {
+    Rollback createNonStagedRollback(int rollbackId, int userId, String installerPackageName) {
         File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId));
-        return new Rollback(rollbackId, backupDir, -1);
+        return new Rollback(rollbackId, backupDir, -1, userId, installerPackageName);
     }
 
     /**
      * Creates a new Rollback instance for a staged rollback with
      * backupDir assigned.
      */
-    Rollback createStagedRollback(int rollbackId, int stagedSessionId) {
+    Rollback createStagedRollback(int rollbackId, int stagedSessionId, int userId,
+            String installerPackageName) {
         File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId));
-        return new Rollback(rollbackId, backupDir, stagedSessionId);
+        return new Rollback(rollbackId, backupDir, stagedSessionId, userId, installerPackageName);
     }
 
     /**
@@ -263,6 +266,8 @@
             dataJson.put("state", rollback.getStateAsString());
             dataJson.put("apkSessionId", rollback.getApkSessionId());
             dataJson.put("restoreUserDataInProgress", rollback.isRestoreUserDataInProgress());
+            dataJson.put("userId", rollback.getUserId());
+            dataJson.putOpt("installerPackageName", rollback.getInstallerPackageName());
 
             PrintWriter pw = new PrintWriter(new File(rollback.getBackupDir(), "rollback.json"));
             pw.println(dataJson.toString());
@@ -305,7 +310,9 @@
                 dataJson.getInt("stagedSessionId"),
                 rollbackStateFromString(dataJson.getString("state")),
                 dataJson.getInt("apkSessionId"),
-                dataJson.getBoolean("restoreUserDataInProgress"));
+                dataJson.getBoolean("restoreUserDataInProgress"),
+                dataJson.optInt("userId", USER_SYSTEM),
+                dataJson.optString("installerPackageName", ""));
     }
 
     private static JSONObject toJson(VersionedPackage pkg) throws JSONException {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 3439d38..65bb2342 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -29,6 +29,7 @@
 import android.hardware.biometrics.IBiometricServiceReceiverInternal;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManager.DisplayListener;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -1334,6 +1335,18 @@
     }
 
     @Override
+    public void grantInlineReplyUriPermission(String key, Uri uri) {
+        enforceStatusBarService();
+        int callingUid = Binder.getCallingUid();
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mNotificationDelegate.grantInlineReplyUriPermission(key, uri, callingUid);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
             String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
         (new StatusBarShellCommand(this, mContext)).exec(
diff --git a/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java
new file mode 100644
index 0000000..852f707
--- /dev/null
+++ b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java
@@ -0,0 +1,39 @@
+/*
+ * 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.server.updates;
+
+import android.content.Context;
+import android.content.Intent;
+import android.util.Slog;
+
+/**
+ * Emergency Number Database Install Receiver.
+ */
+public class EmergencyNumberDbInstallReceiver extends ConfigUpdateInstallReceiver {
+
+    private static final String TAG = "EmergencyNumberDbInstallReceiver";
+
+    public EmergencyNumberDbInstallReceiver() {
+        super("/data/misc/emergencynumberdb", "emergency_number_db", "metadata/", "version");
+    }
+
+    @Override
+    protected void postInstall(Context context, Intent intent) {
+        Slog.i(TAG, "Emergency number database is updated in file partition");
+        // TODO Send a notification to EmergencyNumberTracker for updating of emergency number db.
+    }
+}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 3cdb59b..3663f46 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1228,6 +1228,7 @@
                         saveSettingsLocked(mWallpaper.userId);
                     }
                     FgThread.getHandler().removeCallbacks(mResetRunnable);
+                    mContext.getMainThreadHandler().removeCallbacks(this::tryToRebind);
                 }
             }
         }
@@ -1270,6 +1271,34 @@
             }
         }
 
+        private void tryToRebind() {
+            synchronized (mLock) {
+                if (mWallpaper.wallpaperUpdating) {
+                    return;
+                }
+                final ComponentName wpService = mWallpaper.wallpaperComponent;
+                // The broadcast of package update could be delayed after service disconnected. Try
+                // to re-bind the service for 10 seconds.
+                if (bindWallpaperComponentLocked(
+                        wpService, true, false, mWallpaper, null)) {
+                    mWallpaper.connection.scheduleTimeoutLocked();
+                } else if (SystemClock.uptimeMillis() - mWallpaper.lastDiedTime
+                        < WALLPAPER_RECONNECT_TIMEOUT_MS) {
+                    // Bind fail without timeout, schedule rebind
+                    Slog.w(TAG, "Rebind fail! Try again later");
+                    mContext.getMainThreadHandler().postDelayed(this::tryToRebind, 1000);
+                } else {
+                    // Timeout
+                    Slog.w(TAG, "Reverting to built-in wallpaper!");
+                    clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
+                    final String flattened = wpService.flattenToString();
+                    EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
+                            flattened.substring(0, Math.min(flattened.length(),
+                                    MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
+                }
+            }
+        }
+
         private void processDisconnect(final ServiceConnection connection) {
             synchronized (mLock) {
                 // The wallpaper disappeared.  If this isn't a system-default one, track
@@ -1293,20 +1322,8 @@
                             clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
                         } else {
                             mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
-
-                            clearWallpaperComponentLocked(mWallpaper);
-                            if (bindWallpaperComponentLocked(
-                                    wpService, false, false, mWallpaper, null)) {
-                                mWallpaper.connection.scheduleTimeoutLocked();
-                            } else {
-                                Slog.w(TAG, "Reverting to built-in wallpaper!");
-                                clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
-                            }
+                            tryToRebind();
                         }
-                        final String flattened = wpService.flattenToString();
-                        EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
-                                flattened.substring(0, Math.min(flattened.length(),
-                                        MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
                     }
                 } else {
                     if (DEBUG_LIVE) {
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 10415f5..b131ab6 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -725,7 +725,7 @@
             }
 
             private Region getLetterboxBounds(WindowState windowState) {
-                final AppWindowToken appToken = windowState.mAppToken;
+                final ActivityRecord appToken = windowState.mActivityRecord;
                 if (appToken == null) {
                     return new Region();
                 }
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 9d9a37c..48a7b73 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -1294,14 +1294,14 @@
         if (mDisplayContent == null) {
             return;
         }
-        final AppWindowToken newFocus;
+        final ActivityRecord newFocus;
         final IBinder token = r.appToken;
         if (token == null) {
             ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Clearing focused app, displayId=%d",
                     mDisplayId);
             newFocus = null;
         } else {
-            newFocus = mService.mWindowManager.mRoot.getAppWindowToken(token);
+            newFocus = mService.mWindowManager.mRoot.getActivityRecord(token);
             if (newFocus == null) {
                 Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token
                         + ", displayId=" + mDisplayId);
@@ -1430,9 +1430,8 @@
                 continue;
             }
 
-            final ArrayList<ActivityRecord> activities = task.mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 if (r.isActivityTypeHome()
                         && ((userId == UserHandle.USER_ALL) || (r.mUserId == userId))) {
                     return r;
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
index eff0f75..c6b17e2 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
@@ -39,8 +39,13 @@
  * If an activity is successfully started, the launch sequence's state will transition into
  * {@code STARTED} via {@link #onActivityLaunched}. This is a transient state.
  *
- * It must then transition to either {@code CANCELLED} with {@link #onActivityLaunchCancelled}
- * or into {@code FINISHED} with {@link #onActivityLaunchFinished}. These are terminal states.
+ * It must then transition to either {@code CANCELLED} with {@link #onActivityLaunchCancelled},
+ * which is a terminal state or into {@code FINISHED} with {@link #onActivityLaunchFinished}.
+ *
+ * The {@code FINISHED} with {@link #onActivityLaunchFinished} then may transition to
+ * {@code FULLY_DRAWN} with {@link #onReportFullyDrawn}, which is a terminal state.
+ * Note this transition may not happen if the reportFullyDrawn event is not receivied,
+ * in which case {@code FINISHED} is terminal.
  *
  * Note that the {@code ActivityRecordProto} provided as a parameter to some state transitions isn't
  * necessarily the same within a single launch sequence: it is only the top-most activity at the
@@ -51,15 +56,15 @@
  * until a subsequent transition into {@code INTENT_STARTED} initiates a new launch sequence.
  *
  * <pre>
- *        ┌⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┐     ┌⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┐     ╔══════════════════════════╗
- *    ╴╴▶ ⋮ INTENT_STARTED ⋮ ──▶ ⋮     ACTIVITY_LAUNCHED     ⋮ ──▶ ║ ACTIVITY_LAUNCH_FINISHED ║
- *        └⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┘     └⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┘     ╚══════════════════════════╝
- *          :                      :
- *          :                      :
- *          ▼                      ▼
- *        ╔════════════════╗     ╔═══════════════════════════╗
- *        ║ INTENT_FAILED  ║     ║ ACTIVITY_LAUNCH_CANCELLED ║
- *        ╚════════════════╝     ╚═══════════════════════════╝
+ *        ┌⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┐     ┌⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┐     ┌--------------------------┐
+ *    ╴╴▶  INTENT_STARTED    ──▶      ACTIVITY_LAUNCHED        ──▶   ACTIVITY_LAUNCH_FINISHED
+ *        └⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┘     └⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┘     └--------------------------┘
+ *          :                      :                                 :
+ *          :                      :                                 :
+ *          ▼                      ▼                                 ▼
+ *        ╔════════════════╗     ╔═══════════════════════════╗     ╔═══════════════════════════╗
+ *        ║ INTENT_FAILED  ║     ║ ACTIVITY_LAUNCH_CANCELLED ║     ║    REPORT_FULLY_DRAWN     ║
+ *        ╚════════════════╝     ╚═══════════════════════════╝     ╚═══════════════════════════╝
  * </pre>
  */
 public interface ActivityMetricsLaunchObserver {
@@ -111,7 +116,7 @@
      * Multiple calls to this method cannot occur without first terminating the current
      * launch sequence.
      */
-    public void onIntentStarted(@NonNull Intent intent);
+    public void onIntentStarted(@NonNull Intent intent, long timestampNanos);
 
     /**
      * Notifies the observer that the current launch sequence has failed to launch an activity.
@@ -177,6 +182,9 @@
      * drawn for the first time: the top-most activity at the time is what's reported here.
      *
      * @param finalActivity the top-most activity whose windows were first to fully draw
+     * @param timestampNanos the timestamp of ActivityLaunchFinished event in nanoseconds.
+     *        To compute the TotalTime duration, deduct the timestamp {@link #onIntentStarted}
+     *        from {@code timestampNanos}.
      *
      * Multiple calls to this method cannot occur without first terminating the current
      * launch sequence.
@@ -186,5 +194,22 @@
      *          and only the latest activity that was top-most during first-frame drawn
      *          is reported here.
      */
-    public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] finalActivity);
+    public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] finalActivity,
+                                         long timestampNanos);
+
+    /**
+     * Notifies the observer that the application self-reported itself as being fully drawn.
+     *
+     * @param activity the activity that triggers the ReportFullyDrawn event.
+     * @param timestampNanos the timestamp of ReportFullyDrawn event in nanoseconds.
+     *        To compute the duration, deduct the deduct the timestamp {@link #onIntentStarted}
+     *        from {@code timestampNanos}.
+     *
+     * @apiNote The behavior of ReportFullyDrawn mostly depends on the app.
+     *          It is used as an accurate estimate of meanfully app startup time.
+     *          This event may be missing for many apps.
+     */
+    public void onReportFullyDrawn(@NonNull @ActivityRecordProto byte[] activity,
+        long timestampNanos);
+
 }
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index a0a2967..e6c6b12e 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -92,6 +92,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.SomeArgs;
 import com.android.server.LocalServices;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Listens to activity launches, transitions, visibility changes and window drawn callbacks to
@@ -132,8 +133,8 @@
 
     // set to INVALID_START_TIME in reset.
     // set to valid value in notifyActivityLaunching
-    private long mCurrentTransitionStartTime = INVALID_START_TIME;
-    private long mLastTransitionStartTime = INVALID_START_TIME;
+    private long mCurrentTransitionStartTimeNs = INVALID_START_TIME;
+    private long mLastTransitionStartTimeNs = INVALID_START_TIME;
 
     private int mCurrentTransitionDeviceUptime;
     private int mCurrentTransitionDelayMs;
@@ -326,12 +327,12 @@
                                       intent));
         }
 
-        if (mCurrentTransitionStartTime == INVALID_START_TIME) {
+        if (mCurrentTransitionStartTimeNs == INVALID_START_TIME) {
 
-            mCurrentTransitionStartTime = SystemClock.uptimeMillis();
-            mLastTransitionStartTime = mCurrentTransitionStartTime;
+            mCurrentTransitionStartTimeNs = SystemClock.elapsedRealtimeNanos();
+            mLastTransitionStartTimeNs = mCurrentTransitionStartTimeNs;
 
-            launchObserverNotifyIntentStarted(intent);
+            launchObserverNotifyIntentStarted(intent, mCurrentTransitionStartTimeNs);
         }
     }
 
@@ -382,14 +383,15 @@
                 ? launchedActivity.getWindowingMode()
                 : WINDOWING_MODE_UNDEFINED;
         final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
-        if (mCurrentTransitionStartTime == INVALID_START_TIME) {
+        if (mCurrentTransitionStartTimeNs == INVALID_START_TIME) {
             // No transition is active ignore this launch.
             return;
         }
 
         if (launchedActivity != null && launchedActivity.mDrawn) {
             // Launched activity is already visible. We cannot measure windows drawn delay.
-            reset(true /* abort */, info, "launched activity already visible");
+            reset(true /* abort */, info, "launched activity already visible",
+                0L /* timestampNs */);
             return;
         }
 
@@ -407,7 +409,8 @@
         if ((!isLoggableResultCode(resultCode) || launchedActivity == null || !processSwitch
                 || windowingMode == WINDOWING_MODE_UNDEFINED) && !otherWindowModesLaunching) {
             // Failed to launch or it was not a process switch, so we don't care about the timing.
-            reset(true /* abort */, info, "failed to launch or not a process switch");
+            reset(true /* abort */, info, "failed to launch or not a process switch",
+                0L /* timestampNs */);
             return;
         } else if (otherWindowModesLaunching) {
             // Don't log this windowing mode but continue with the other windowing modes.
@@ -441,19 +444,20 @@
      * Notifies the tracker that all windows of the app have been drawn.
      */
     WindowingModeTransitionInfoSnapshot notifyWindowsDrawn(@WindowingMode int windowingMode,
-                                                           long timestamp) {
+                                                           long timestampNs) {
         if (DEBUG_METRICS) Slog.i(TAG, "notifyWindowsDrawn windowingMode=" + windowingMode);
 
         final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
         if (info == null || info.loggedWindowsDrawn) {
             return null;
         }
-        info.windowsDrawnDelayMs = calculateDelay(timestamp);
+        info.windowsDrawnDelayMs = calculateDelay(timestampNs);
         info.loggedWindowsDrawn = true;
         final WindowingModeTransitionInfoSnapshot infoSnapshot =
                 new WindowingModeTransitionInfoSnapshot(info);
         if (allWindowsDrawn() && mLoggedTransitionStarting) {
-            reset(false /* abort */, info, "notifyWindowsDrawn - all windows drawn");
+            reset(false /* abort */, info, "notifyWindowsDrawn - all windows drawn",
+                timestampNs /* timestampNs */);
         }
         return infoSnapshot;
     }
@@ -476,7 +480,7 @@
      * @param windowingModeToReason A map from windowing mode to a reason integer, which must be on
      *                              of ActivityTaskManagerInternal.APP_TRANSITION_* reasons.
      */
-    void notifyTransitionStarting(SparseIntArray windowingModeToReason, long timestamp) {
+    void notifyTransitionStarting(SparseIntArray windowingModeToReason, long timestampNs) {
         if (!isAnyTransitionActive() || mLoggedTransitionStarting) {
             // Ignore calls to this made after a reset and prior to notifyActivityLaunching.
 
@@ -484,7 +488,7 @@
             return;
         }
         if (DEBUG_METRICS) Slog.i(TAG, "notifyTransitionStarting");
-        mCurrentTransitionDelayMs = calculateDelay(timestamp);
+        mCurrentTransitionDelayMs = calculateDelay(timestampNs);
         mLoggedTransitionStarting = true;
 
         WindowingModeTransitionInfo foundInfo = null;
@@ -501,7 +505,8 @@
         if (allWindowsDrawn()) {
             // abort metrics collection if we cannot find a matching transition.
             final boolean abortMetrics = foundInfo == null;
-            reset(abortMetrics, foundInfo, "notifyTransitionStarting - all windows drawn");
+            reset(abortMetrics, foundInfo, "notifyTransitionStarting - all windows drawn",
+                timestampNs /* timestampNs */);
         }
     }
 
@@ -527,8 +532,8 @@
     }
 
     private boolean hasVisibleNonFinishingActivity(TaskRecord t) {
-        for (int i = t.mActivities.size() - 1; i >= 0; --i) {
-            final ActivityRecord r = t.mActivities.get(i);
+        for (int i = t.getChildCount() - 1; i >= 0; --i) {
+            final ActivityRecord r = t.getChildAt(i);
             if (r.visible && !r.finishing) {
                 return true;
             }
@@ -567,7 +572,8 @@
             logAppTransitionCancel(info);
             mWindowingModeTransitionInfo.remove(r.getWindowingMode());
             if (mWindowingModeTransitionInfo.size() == 0) {
-                reset(true /* abort */, info, "notifyVisibilityChanged to invisible");
+                reset(true /* abort */, info, "notifyVisibilityChanged to invisible",
+                    0L /* timestampNs */);
             }
         }
     }
@@ -598,12 +604,16 @@
     }
 
     private boolean isAnyTransitionActive() {
-        return mCurrentTransitionStartTime != INVALID_START_TIME
+        return mCurrentTransitionStartTimeNs != INVALID_START_TIME
                 && mWindowingModeTransitionInfo.size() > 0;
     }
 
-    private void reset(boolean abort, WindowingModeTransitionInfo info, String cause) {
-        if (DEBUG_METRICS) Slog.i(TAG, "reset abort=" + abort + ",cause=" + cause);
+    private void reset(boolean abort, WindowingModeTransitionInfo info, String cause,
+        long timestampNs) {
+        if (DEBUG_METRICS) {
+            Slog.i(TAG,
+                "reset abort=" + abort + ",cause=" + cause + ",timestamp=" + timestampNs);
+        }
         if (!abort && isAnyTransitionActive()) {
             logAppTransitionMultiEvents();
         }
@@ -615,13 +625,13 @@
             if (abort) {
                 launchObserverNotifyActivityLaunchCancelled(info);
             } else {
-                launchObserverNotifyActivityLaunchFinished(info);
+                launchObserverNotifyActivityLaunchFinished(info, timestampNs);
             }
         } else {
             launchObserverNotifyIntentFailed();
         }
 
-        mCurrentTransitionStartTime = INVALID_START_TIME;
+        mCurrentTransitionStartTimeNs = INVALID_START_TIME;
         mCurrentTransitionDelayMs = INVALID_DELAY;
         mLoggedTransitionStarting = false;
         mWindowingModeTransitionInfo.clear();
@@ -629,12 +639,14 @@
 
     private int calculateCurrentDelay() {
         // Shouldn't take more than 25 days to launch an app, so int is fine here.
-        return (int) (SystemClock.uptimeMillis() - mCurrentTransitionStartTime);
+        return (int) TimeUnit.NANOSECONDS
+            .toMillis(SystemClock.elapsedRealtimeNanos() - mCurrentTransitionStartTimeNs);
     }
 
-    private int calculateDelay(long timestamp) {
+    private int calculateDelay(long timestampNs) {
         // Shouldn't take more than 25 days to launch an app, so int is fine here.
-        return (int) (timestamp - mCurrentTransitionStartTime);
+        return (int) TimeUnit.NANOSECONDS.toMillis(timestampNs -
+            mCurrentTransitionStartTimeNs);
     }
 
     private void logAppTransitionCancel(WindowingModeTransitionInfo info) {
@@ -679,7 +691,7 @@
             // Take a snapshot of the transition info before sending it to the handler for logging.
             // This will avoid any races with other operations that modify the ActivityRecord.
             final WindowingModeTransitionInfoSnapshot infoSnapshot =
-                    new WindowingModeTransitionInfoSnapshot(info);
+                     new WindowingModeTransitionInfoSnapshot(info);
             final int currentTransitionDeviceUptime = mCurrentTransitionDeviceUptime;
             final int currentTransitionDelayMs = mCurrentTransitionDelayMs;
             BackgroundThread.getHandler().post(() -> logAppTransition(
@@ -811,7 +823,9 @@
         final LogMaker builder = new LogMaker(APP_TRANSITION_REPORTED_DRAWN);
         builder.setPackageName(r.packageName);
         builder.addTaggedData(FIELD_CLASS_NAME, r.info.name);
-        long startupTimeMs = SystemClock.uptimeMillis() - mLastTransitionStartTime;
+        long currentTimestampNs = SystemClock.elapsedRealtimeNanos();
+        long startupTimeMs =
+            TimeUnit.NANOSECONDS.toMillis(currentTimestampNs - mLastTransitionStartTimeNs);
         builder.addTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS, startupTimeMs);
         builder.setType(restoredFromBundle
                 ? TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE
@@ -837,6 +851,10 @@
         final WindowingModeTransitionInfoSnapshot infoSnapshot =
                 new WindowingModeTransitionInfoSnapshot(info, r, (int) startupTimeMs);
         BackgroundThread.getHandler().post(() -> logAppFullyDrawn(infoSnapshot));
+
+        // Notify reportFullyDrawn event.
+        launchObserverNotifyReportFullyDrawn(r, currentTimestampNs);
+
         return infoSnapshot;
     }
 
@@ -1006,12 +1024,12 @@
     }
 
     /** Notify the {@link ActivityMetricsLaunchObserver} that a new launch sequence has begun. */
-    private void launchObserverNotifyIntentStarted(Intent intent) {
+    private void launchObserverNotifyIntentStarted(Intent intent, long timestampNs) {
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                 "MetricsLogger:launchObserverNotifyIntentStarted");
 
         // Beginning a launch is timing sensitive and so should be observed as soon as possible.
-        mLaunchObserver.onIntentStarted(intent);
+        mLaunchObserver.onIntentStarted(intent, timestampNs);
 
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
@@ -1049,6 +1067,16 @@
     }
 
     /**
+     * Notifies the {@link ActivityMetricsLaunchObserver} the reportFullDrawn event.
+     */
+    private void launchObserverNotifyReportFullyDrawn(ActivityRecord r, long timestampNs) {
+        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+            "MetricsLogger:launchObserverNotifyReportFullyDrawn");
+        mLaunchObserver.onReportFullyDrawn(convertActivityRecordToProto(r), timestampNs);
+        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+    }
+
+    /**
      * Notify the {@link ActivityMetricsLaunchObserver} that the current launch sequence is
      * cancelled.
      */
@@ -1068,12 +1096,14 @@
      * Notify the {@link ActivityMetricsLaunchObserver} that the current launch sequence's activity
      * has fully finished (successfully).
      */
-    private void launchObserverNotifyActivityLaunchFinished(WindowingModeTransitionInfo info) {
+    private void launchObserverNotifyActivityLaunchFinished(WindowingModeTransitionInfo info,
+        long timestampNs) {
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                 "MetricsLogger:launchObserverNotifyActivityLaunchFinished");
 
-        mLaunchObserver.onActivityLaunchFinished(
-                convertActivityRecordToProto(info.launchedActivity));
+        mLaunchObserver
+            .onActivityLaunchFinished(convertActivityRecordToProto(info.launchedActivity),
+                timestampNs);
 
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 4f52d9d..3853841 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -41,6 +41,10 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.app.WindowConfiguration.activityTypeToString;
 import static android.content.Intent.ACTION_MAIN;
 import static android.content.Intent.CATEGORY_HOME;
@@ -54,14 +58,19 @@
 import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
 import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
 import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
+import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
 import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
 import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
+import static android.content.pm.ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
 import static android.content.pm.ActivityInfo.FLAG_MULTIPROCESS;
 import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY;
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
 import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
+import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
+import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
+import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
@@ -72,6 +81,8 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
 import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
 import static android.content.res.Configuration.EMPTY;
@@ -80,14 +91,29 @@
 import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
 import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
+import static android.os.Build.VERSION_CODES.HONEYCOMB;
 import static android.os.Build.VERSION_CODES.O;
 import static android.os.Process.SYSTEM_UID;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.view.Display.COLOR_MODE_DEFAULT;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
+import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
+import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
 import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
+import static android.view.WindowManager.TRANSIT_UNSET;
+import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
 
 import static com.android.server.am.ActivityRecordProto.APP_WINDOW_TOKEN;
 import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
@@ -98,6 +124,8 @@
 import static com.android.server.am.ActivityRecordProto.VISIBLE;
 import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
 import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
 import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
@@ -144,13 +172,52 @@
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutLocked;
+import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
+import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
+import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
+import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
+import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
+import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
+import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
+import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
+import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
+import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
+import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
+import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
+import static com.android.server.wm.AppWindowTokenProto.NAME;
+import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
+import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
+import static com.android.server.wm.AppWindowTokenProto.REMOVED;
+import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
+import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
+import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
+import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
+import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
+import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
+import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
+import static com.android.server.wm.IdentifierProto.HASH_CODE;
+import static com.android.server.wm.IdentifierProto.TITLE;
+import static com.android.server.wm.IdentifierProto.USER_ID;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutLocked;
 import static com.android.server.wm.TaskPersister.DEBUG;
 import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.logWithStack;
+import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
+import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
 
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
@@ -159,7 +226,9 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.Size;
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.ActivityManager.TaskDescription;
 import android.app.ActivityOptions;
 import android.app.PendingIntent;
@@ -189,8 +258,11 @@
 import android.content.pm.ApplicationInfo;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.GraphicBuffer;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Binder;
@@ -202,6 +274,8 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.Trace;
+import android.os.UserHandle;
 import android.os.storage.StorageManager;
 import android.service.voice.IVoiceInteractionSession;
 import android.util.ArraySet;
@@ -213,21 +287,36 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.AppTransitionAnimationSpec;
 import android.view.DisplayCutout;
+import android.view.DisplayInfo;
 import android.view.IAppTransitionAnimationSpecsFuture;
 import android.view.IApplicationToken;
+import android.view.InputApplicationHandle;
+import android.view.RemoteAnimationAdapter;
+import android.view.RemoteAnimationDefinition;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
+import android.view.animation.Animation;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.content.ReferrerIntent;
+import com.android.internal.R;
+import com.android.internal.util.ToBooleanFunction;
 import com.android.internal.util.XmlUtils;
+import com.android.server.AttributeCache;
+import com.android.server.LocalServices;
 import com.android.server.am.AppTimeTracker;
 import com.android.server.am.EventLogTags;
 import com.android.server.am.PendingIntentRecord;
+import com.android.server.display.color.ColorDisplayService;
+import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.protolog.common.ProtoLog;
 import com.android.server.uri.UriPermissionOwner;
 import com.android.server.wm.ActivityMetricsLogger.WindowingModeTransitionInfoSnapshot;
 import com.android.server.wm.ActivityStack.ActivityState;
+import com.android.server.wm.WindowManagerService.H;
 
 import com.google.android.collect.Sets;
 
@@ -239,16 +328,18 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
+import java.util.function.Consumer;
 
 /**
  * An entry in the history stack, representing an activity.
  */
-final class ActivityRecord extends AppWindowToken {
+final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_ATM;
     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
     private static final String TAG_APP = TAG + POSTFIX_APP;
@@ -277,8 +368,34 @@
     // How many activities have to be scheduled to stop to force a stop pass.
     private static final int MAX_STOPPING_TO_FORCE = 3;
 
-    // TODO: Move to AppWindowToken?
+    private static final int STARTING_WINDOW_TYPE_NONE = 0;
+    private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
+    private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
+
+    /**
+     * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
+     */
+    @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
+
+    final ActivityTaskManagerService mAtmService;
     final ActivityInfo info; // activity info provided by developer in AndroidManifest
+    // Non-null only for application tokens.
+    // TODO: rename to mActivityToken
+    final ActivityRecord.Token appToken;
+    // Which user is this running for?
+    final int mUserId;
+    // The package implementing intent's component
+    // TODO: rename to mPackageName
+    final String packageName;
+    // the intent component, or target of an alias.
+    final ComponentName mActivityComponent;
+    // Has a wallpaper window as a background.
+    // TODO: Rename to mHasWallpaper and also see if it possible to combine this with the
+    // mOccludesParent field.
+    final boolean hasWallpaper;
+    // Input application handle used by the input dispatcher.
+    final InputApplicationHandle mInputApplicationHandle;
+
     final int launchedFromPid; // always the pid who started the activity.
     final int launchedFromUid; // always the uid who started the activity.
     final String launchedFromPackage; // always the package who started the activity.
@@ -318,6 +435,7 @@
     ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
     HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
     ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
+    Intent mLastNewIntent;  // the last new intent we delivered to client
     ActivityOptions pendingOptions; // most recently given options
     ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
     AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
@@ -347,9 +465,14 @@
     boolean visible;        // does this activity's window need to be shown?
     boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
                                      // might hide this activity?
-    // TODO: figureout how to consolidate with the same variable in AppWindowToken.
+    // True if the hidden state of this token was forced to false due to a transferred starting
+    // window.
+    private boolean mHiddenSetFromTransferredStartingWindow;
+    // TODO: figureout how to consolidate with the same variable in ActivityRecord.
     private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
                                         // process that it is hidden.
+    private boolean mLastDeferHidingClient; // If true we will defer setting mClientHidden to true
+                                           // and reporting to the client that it is hidden.
     boolean sleeping;       // have we told the activity to sleep?
     boolean nowVisible;     // is this activity's window visible?
     boolean mDrawn;          // is this activity's window drawn?
@@ -400,6 +523,188 @@
     boolean pendingVoiceInteractionStart;   // Waiting for activity-invoked voice session
     IVoiceInteractionSession voiceSession;  // Voice interaction session for this activity
 
+    boolean mVoiceInteraction;
+
+    private int mPendingRelaunchCount;
+
+    // True if we are current in the process of removing this app token from the display
+    private boolean mRemovingFromDisplay = false;
+
+    // Flag set while reparenting to prevent actions normally triggered by an individual parent
+    // change.
+    private boolean mReparenting;
+
+    private RemoteAnimationDefinition mRemoteAnimationDefinition;
+
+    private AnimatingActivityRegistry mAnimatingActivityRegistry;
+
+    private Task mLastParent;
+
+    // Have we told the window clients to hide themselves?
+    private boolean mClientHidden;
+
+    boolean firstWindowDrawn;
+    // Last drawn state we reported to the app token.
+    private boolean reportedDrawn;
+    private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
+            new WindowState.UpdateReportedVisibilityResults();
+
+    private boolean mUseTransferredAnimation;
+
+    /**
+     * @see #currentLaunchCanTurnScreenOn()
+     */
+    private boolean mCurrentLaunchCanTurnScreenOn = true;
+
+    /**
+     * This gets used during some open/close transitions as well as during a change transition
+     * where it represents the starting-state snapshot.
+     */
+    private AppWindowThumbnail mThumbnail;
+    private final Rect mTransitStartRect = new Rect();
+
+    /**
+     * If we are running an animation, this determines the transition type. Must be one of
+     * AppTransition.TRANSIT_* constants.
+     */
+    private int mTransit;
+
+    /**
+     * If we are running an animation, this determines the flags during this animation. Must be a
+     * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
+     */
+    private int mTransitFlags;
+    /**
+     * This leash is used to "freeze" the app surface in place after the state change, but before
+     * the animation is ready to start.
+     */
+    private SurfaceControl mTransitChangeLeash = null;
+
+    /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
+    private boolean mLastSurfaceShowing = true;
+
+    private Letterbox mLetterbox;
+
+    /**
+     * The activity is opaque and fills the entire space of this task.
+     * @see WindowContainer#fillsParent()
+     */
+    private boolean mOccludesParent;
+
+    // The input dispatching timeout for this application token in nanoseconds.
+    long mInputDispatchingTimeoutNanos;
+
+    private boolean mShowWhenLocked;
+    private boolean mInheritShownWhenLocked;
+    private boolean mTurnScreenOn;
+
+    /** Have we been asked to have this token keep the screen frozen? */
+    private boolean mFreezingScreen;
+
+    // These are used for determining when all windows associated with
+    // an activity have been drawn, so they can be made visible together
+    // at the same time.
+    // initialize so that it doesn't match mTransactionSequence which is an int.
+    private long mLastTransactionSequence = Long.MIN_VALUE;
+    private int mNumInterestingWindows;
+    private int mNumDrawnWindows;
+    boolean inPendingTransaction;
+    boolean allDrawn;
+    private boolean mLastAllDrawn;
+
+    private boolean mLastContainsShowWhenLockedWindow;
+    private boolean mLastContainsDismissKeyguardWindow;
+
+    /**
+     * A flag to determine if this AR is in the process of closing or entering PIP. This is needed
+     * to help AR know that the app is in the process of closing but hasn't yet started closing on
+     * the WM side.
+     */
+    private boolean mWillCloseOrEnterPip;
+
+    /**
+     * The scale to fit at least one side of the activity to its parent. If the activity uses
+     * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
+     */
+    private float mSizeCompatScale = 1f;
+    /**
+     * The bounds in global coordinates for activity in size compatibility mode.
+     * @see ActivityRecord#hasSizeCompatBounds()
+     */
+    private Rect mSizeCompatBounds;
+
+    // activity is not displayed?
+    // TODO: rename to mNoDisplay
+    @VisibleForTesting
+    boolean noDisplay;
+    boolean mShowForAllUsers;
+    // TODO: Make this final
+    int mTargetSdk;
+
+    // Set to true when this app creates a surface while in the middle of an animation. In that
+    // case do not clear allDrawn until the animation completes.
+    boolean deferClearAllDrawn;
+
+    // Is this window's surface needed?  This is almost like hidden, except
+    // it will sometimes be true a little earlier: when the token has
+    // been shown, but is still waiting for its app transition to execute
+    // before making its windows shown.
+    boolean hiddenRequested;
+
+    // Last visibility state we reported to the app token.
+    boolean reportedVisible;
+
+    // Set to true when the token has been removed from the window mgr.
+    boolean removed;
+
+    boolean mDisablePreviewScreenshots;
+
+    // Information about an application starting window if displayed.
+    // Note: these are de-referenced before the starting window animates away.
+    StartingData mStartingData;
+    WindowState startingWindow;
+    WindowManagerPolicy.StartingSurface startingSurface;
+    boolean startingDisplayed;
+    boolean startingMoved;
+
+    // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
+    boolean mIsExiting;
+
+    boolean mLaunchTaskBehind;
+    boolean mEnteringAnimation;
+
+    boolean mAppStopped;
+    // A hint to override the window specified rotation animation, or -1 to use the window specified
+    // value. We use this so that we can select the right animation in the cases of starting
+    // windows, where the app hasn't had time to set a value on the window.
+    int mRotationAnimationHint = -1;
+
+    ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
+    ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
+
+    /** Whether this token should be boosted at the top of all app window tokens. */
+    @VisibleForTesting boolean mNeedsZBoost;
+
+    /** Layer used to constrain the animation to a token's stack bounds. */
+    SurfaceControl mAnimationBoundsLayer;
+
+    /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
+    boolean mNeedsAnimationBoundsLayer;
+
+    private AppSaturationInfo mLastAppSaturationInfo;
+
+    private final ColorDisplayService.ColorTransformController mColorTransformController =
+            (matrix, translation) -> mWmService.mH.post(() -> {
+                synchronized (mWmService.mGlobalLock) {
+                    if (mLastAppSaturationInfo == null) {
+                        mLastAppSaturationInfo = new AppSaturationInfo();
+                    }
+
+                    mLastAppSaturationInfo.setSaturation(matrix, translation);
+                    updateColorTransform();
+                }
+            });
+
     /**
      * Current sequencing integer of the configuration, for skipping old activity configurations.
      */
@@ -411,6 +716,10 @@
     private final Configuration mTmpConfig = new Configuration();
     private final Rect mTmpBounds = new Rect();
 
+    private final Point mTmpPoint = new Point();
+    private final Rect mTmpRect = new Rect();
+    private final Rect mTmpPrevBounds = new Rect();
+
     // Token for targeting this activity for assist purposes.
     final Binder assistToken = new Binder();
 
@@ -428,6 +737,13 @@
     }
 
     void dump(PrintWriter pw, String prefix) {
+    }
+
+    /**
+     * Copied from old AppWindowToken.
+     */
+    @Override
+    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
         final long now = SystemClock.uptimeMillis();
         pw.print(prefix); pw.print("packageName="); pw.print(packageName);
                 pw.print(" processName="); pw.println(processName);
@@ -575,6 +891,64 @@
             pw.print("requestedVrComponent=");
             pw.println(requestedVrComponent);
         }
+        super.dump(pw, prefix, dumpAll);
+        if (appToken != null) {
+            pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
+        }
+        pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
+        pw.print(" mOrientation="); pw.println(mOrientation);
+        pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
+                + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
+                + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
+        if (paused) {
+            pw.print(prefix); pw.print("paused="); pw.println(paused);
+        }
+        if (mAppStopped) {
+            pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
+        }
+        if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
+                || allDrawn || mLastAllDrawn) {
+            pw.print(prefix); pw.print("mNumInterestingWindows=");
+            pw.print(mNumInterestingWindows);
+            pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
+            pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
+            pw.print(" allDrawn="); pw.print(allDrawn);
+            pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
+            pw.println(")");
+        }
+        if (inPendingTransaction) {
+            pw.print(prefix); pw.print("inPendingTransaction=");
+            pw.println(inPendingTransaction);
+        }
+        if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
+            pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
+            pw.print(" removed="); pw.print(removed);
+            pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
+            pw.print(" mIsExiting="); pw.println(mIsExiting);
+        }
+        if (startingWindow != null || startingSurface != null
+                || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
+            pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
+            pw.print(" startingSurface="); pw.print(startingSurface);
+            pw.print(" startingDisplayed="); pw.print(startingDisplayed);
+            pw.print(" startingMoved="); pw.print(startingMoved);
+            pw.println(" mHiddenSetFromTransferredStartingWindow="
+                    + mHiddenSetFromTransferredStartingWindow);
+        }
+        if (!mFrozenBounds.isEmpty()) {
+            pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
+            pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
+        }
+        if (mPendingRelaunchCount != 0) {
+            pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
+        }
+        if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
+            pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
+                    + mSizeCompatBounds);
+        }
+        if (mRemovingFromDisplay) {
+            pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
+        }
         if (lastVisibleTime != 0 || nowVisible) {
             pw.print(prefix); pw.print(" nowVisible="); pw.print(nowVisible);
                     pw.print(" lastVisibleTime=");
@@ -586,7 +960,8 @@
             pw.println(prefix + "mDeferHidingClient=" + mDeferHidingClient);
         }
         if (deferRelaunchUntilPaused || configChangeFlags != 0) {
-            pw.print(prefix); pw.print("deferRelaunchUntilPaused="); pw.print(deferRelaunchUntilPaused);
+            pw.print(prefix); pw.print("deferRelaunchUntilPaused=");
+                    pw.print(deferRelaunchUntilPaused);
                     pw.print(" configChangeFlags=");
                     pw.println(Integer.toHexString(configChangeFlags));
         }
@@ -900,6 +1275,167 @@
         this.task = task;
     }
 
+    Task getTask() {
+        return (Task) getParent();
+    }
+
+    TaskStack getStack() {
+        final Task task = getTask();
+        if (task != null) {
+            return task.mStack;
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    void onParentChanged() {
+        super.onParentChanged();
+
+        final Task task = getTask();
+
+        // When the associated task is {@code null}, the {@link ActivityRecord} can no longer
+        // access visual elements like the {@link DisplayContent}. We must remove any associations
+        // such as animations.
+        if (!mReparenting) {
+            if (task == null) {
+                // It is possible we have been marked as a closing app earlier. We must remove ourselves
+                // from this list so we do not participate in any future animations.
+                if (getDisplayContent() != null) {
+                    getDisplayContent().mClosingApps.remove(this);
+                }
+            } else if (mLastParent != null && mLastParent.mStack != null) {
+                task.mStack.mExitingActivities.remove(this);
+            }
+        }
+        final TaskStack stack = getStack();
+
+        // If we reparent, make sure to remove ourselves from the old animation registry.
+        if (mAnimatingActivityRegistry != null) {
+            mAnimatingActivityRegistry.notifyFinished(this);
+        }
+        mAnimatingActivityRegistry = stack != null
+                ? stack.getAnimatingActivityRegistry()
+                : null;
+
+        mLastParent = task;
+
+        updateColorTransform();
+    }
+
+    private void updateColorTransform() {
+        if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
+            getPendingTransaction().setColorTransform(mSurfaceControl,
+                    mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
+            mWmService.scheduleAnimationLocked();
+        }
+    }
+
+    @Override
+    void onDisplayChanged(DisplayContent dc) {
+        DisplayContent prevDc = mDisplayContent;
+        super.onDisplayChanged(dc);
+        if (prevDc == null || prevDc == mDisplayContent) {
+            return;
+        }
+
+        if (prevDc.mOpeningApps.remove(this)) {
+            // Transfer opening transition to new display.
+            mDisplayContent.mOpeningApps.add(this);
+            mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
+            mDisplayContent.executeAppTransition();
+        }
+
+        if (prevDc.mChangingApps.remove(this)) {
+            // This gets called *after* the ActivityRecord has been reparented to the new display.
+            // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
+            // so this token is now "frozen" while waiting for the animation to start on prevDc
+            // (which will be cancelled since the window is no-longer a child). However, since this
+            // is no longer a child of prevDc, this won't be notified of the cancelled animation,
+            // so we need to cancel the change transition here.
+            clearChangeLeash(getPendingTransaction(), true /* cancel */);
+        }
+        prevDc.mClosingApps.remove(this);
+
+        if (prevDc.mFocusedApp == this) {
+            prevDc.setFocusedApp(null);
+            final TaskStack stack = dc.getTopStack();
+            if (stack != null) {
+                final Task task = stack.getTopChild();
+                if (task != null && task.getTopChild() == this) {
+                    dc.setFocusedApp(this);
+                }
+            }
+        }
+
+        if (mLetterbox != null) {
+            mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
+        }
+    }
+
+    void layoutLetterbox(WindowState winHint) {
+        final WindowState w = findMainWindow();
+        if (w == null || winHint != null && w != winHint) {
+            return;
+        }
+        final boolean surfaceReady = w.isDrawnLw()  // Regular case
+                || w.mWinAnimator.mSurfaceDestroyDeferred  // The preserved surface is still ready.
+                || w.isDragResizeChanged();  // Waiting for relayoutWindow to call preserveSurface.
+        final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
+        if (needsLetterbox) {
+            if (mLetterbox == null) {
+                mLetterbox = new Letterbox(() -> makeChildSurface(null),
+                        mWmService.mTransactionFactory);
+                mLetterbox.attachInput(w);
+            }
+            getPosition(mTmpPoint);
+            // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
+            // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
+            // is also applied to the task).
+            Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
+                    ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
+            mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
+        } else if (mLetterbox != null) {
+            mLetterbox.hide();
+        }
+    }
+
+    void updateLetterboxSurface(WindowState winHint) {
+        final WindowState w = findMainWindow();
+        if (w != winHint && winHint != null && w != null) {
+            return;
+        }
+        layoutLetterbox(winHint);
+        if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
+            mLetterbox.applySurfaceChanges(getPendingTransaction());
+        }
+    }
+
+    Rect getLetterboxInsets() {
+        if (mLetterbox != null) {
+            return mLetterbox.getInsets();
+        } else {
+            return new Rect();
+        }
+    }
+
+    /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
+    void getLetterboxInnerBounds(Rect outBounds) {
+        if (mLetterbox != null) {
+            outBounds.set(mLetterbox.getInnerFrame());
+        } else {
+            outBounds.setEmpty();
+        }
+    }
+
+    /**
+     * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
+     * the given {@code rect}.
+     */
+    boolean isLetterboxOverlappingWith(Rect rect) {
+        return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
+    }
+
     static class Token extends IApplicationToken.Stub {
         private WeakReference<ActivityRecord> weakActivity;
         private final String name;
@@ -983,16 +1519,82 @@
             ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified,
             boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
             ActivityOptions options, ActivityRecord sourceRecord) {
-        super(_service.mWindowManager, _service, new Token(_intent), aInfo, options, _intent,
-                null /* displayContent */);
+        super(_service.mWindowManager, new Token(_intent).asBinder(), TYPE_APPLICATION, true,
+                null /* displayContent */, false /* ownerCanManageAppTokens */);
+
+        mAtmService = _service;
+        appToken = (Token) token;
+        info = aInfo;
+        mUserId = UserHandle.getUserId(info.applicationInfo.uid);
+        packageName = info.applicationInfo.packageName;
+        mInputApplicationHandle = new InputApplicationHandle(appToken);
+        intent = _intent;
+
+        // If the class name in the intent doesn't match that of the target, this is probably an
+        // alias. We have to create a new ComponentName object to keep track of the real activity
+        // name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
+        if (info.targetActivity == null
+                || (info.targetActivity.equals(intent.getComponent().getClassName())
+                && (info.launchMode == LAUNCH_MULTIPLE
+                || info.launchMode == LAUNCH_SINGLE_TOP))) {
+            mActivityComponent = intent.getComponent();
+        } else {
+            mActivityComponent =
+                    new ComponentName(info.packageName, info.targetActivity);
+        }
+
+        mTargetSdk = info.applicationInfo.targetSdkVersion;
+        mShowForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
+        setOrientation(info.screenOrientation);
+        mRotationAnimationHint = info.rotationAnimation;
+
+        mShowWhenLocked = (aInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0;
+        mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
+        mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
+
+        int realTheme = info.getThemeResource();
+        if (realTheme == Resources.ID_NULL) {
+            realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
+                    ? android.R.style.Theme : android.R.style.Theme_Holo;
+        }
+
+        final AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
+                realTheme, com.android.internal.R.styleable.Window, mUserId);
+
+        if (ent != null) {
+            mOccludesParent = !ActivityInfo.isTranslucentOrFloating(ent.array);
+            hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
+            noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
+        } else {
+            hasWallpaper = false;
+            noDisplay = false;
+        }
+
+        if (options != null) {
+            mLaunchTaskBehind = options.getLaunchTaskBehind();
+
+            final int rotationAnimation = options.getRotationAnimationHint();
+            // Only override manifest supplied option if set.
+            if (rotationAnimation >= 0) {
+                mRotationAnimationHint = rotationAnimation;
+            }
+        }
+
+        // Application tokens start out hidden.
+        setHidden(true);
+        hiddenRequested = true;
+
+        ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
+                ColorDisplayService.ColorDisplayServiceInternal.class);
+        cds.attachColorTransformController(packageName, mUserId,
+                new WeakReference<>(mColorTransformController));
+
         appToken.attach(this);
 
         mRootActivityContainer = _service.mRootActivityContainer;
-        info = aInfo;
         launchedFromPid = _launchedFromPid;
         launchedFromUid = _launchedFromUid;
         launchedFromPackage = _launchedFromPackage;
-        intent = _intent;
         shortComponentName = _intent.getComponent().flattenToShortString();
         resolvedType = _resolvedType;
         componentSpecified = _componentSpecified;
@@ -1074,6 +1676,12 @@
         }
     }
 
+    @Override
+    ActivityRecord asActivityRecord() {
+        // I am an activity record!
+        return this;
+    }
+
     void setProcess(WindowProcessController proc) {
         app = proc;
         final ActivityRecord root = task != null ? task.getRootActivity() : null;
@@ -1090,22 +1698,274 @@
         return hasProcess() && app.hasThread();
     }
 
+    void onAttachToTask(boolean voiceInteraction, DisplayContent dc,
+            long inputDispatchingTimeoutNanos) {
+        mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
+        mVoiceInteraction = voiceInteraction;
+        onDisplayChanged(dc);
+
+        // Application tokens start out hidden.
+        setHidden(true);
+        hiddenRequested = true;
+    }
+
     boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
             CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
             IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
             boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
-        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "setAppStartingWindow: token=%s"
-                    + " pkg=%s transferFrom=%s newTask=%b taskSwitch=%b processRunning=%b"
-                    + " allowTaskSnapshot=%b", appToken, pkg, transferFrom, newTask, taskSwitch,
-                processRunning, allowTaskSnapshot);
-        if (getParent() == null) {
-            Slog.w(TAG_WM, "Attempted to start a window to an app token not having attached to any"
-                    + " task: " + appToken);
+        // If the display is frozen, we won't do anything until the actual window is
+        // displayed so there is no reason to put in the starting window.
+        if (!okToDisplay()) {
             return false;
         }
-        return super.addStartingWindow(pkg, theme, compatInfo, nonLocalizedLabel,
-                labelRes, icon, logo, windowFlags, transferFrom, newTask, taskSwitch,
-                processRunning, allowTaskSnapshot, activityCreated, fromRecents);
+
+        if (mStartingData != null) {
+            return false;
+        }
+
+        final WindowState mainWin = findMainWindow();
+        if (mainWin != null && mainWin.mWinAnimator.getShown()) {
+            // App already has a visible window...why would you want a starting window?
+            return false;
+        }
+
+        final ActivityManager.TaskSnapshot snapshot =
+                mWmService.mTaskSnapshotController.getSnapshot(
+                        getTask().mTaskId, getTask().mUserId,
+                        false /* restoreFromDisk */, false /* reducedResolution */);
+        final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
+                allowTaskSnapshot, activityCreated, fromRecents, snapshot);
+
+        if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
+            return createSnapshot(snapshot);
+        }
+
+        // If this is a translucent window, then don't show a starting window -- the current
+        // effect (a full-screen opaque starting window that fades away to the real contents
+        // when it is ready) does not work for this.
+        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Checking theme of starting window: 0x%x", theme);
+        if (theme != 0) {
+            AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
+                    com.android.internal.R.styleable.Window,
+                    mWmService.mCurrentUserId);
+            if (ent == null) {
+                // Whoops!  App doesn't exist. Um. Okay. We'll just pretend like we didn't
+                // see that.
+                return false;
+            }
+            final boolean windowIsTranslucent = ent.array.getBoolean(
+                    com.android.internal.R.styleable.Window_windowIsTranslucent, false);
+            final boolean windowIsFloating = ent.array.getBoolean(
+                    com.android.internal.R.styleable.Window_windowIsFloating, false);
+            final boolean windowShowWallpaper = ent.array.getBoolean(
+                    com.android.internal.R.styleable.Window_windowShowWallpaper, false);
+            final boolean windowDisableStarting = ent.array.getBoolean(
+                    com.android.internal.R.styleable.Window_windowDisablePreview, false);
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Translucent=%s Floating=%s ShowWallpaper=%s",
+                    windowIsTranslucent, windowIsFloating, windowShowWallpaper);
+            if (windowIsTranslucent) {
+                return false;
+            }
+            if (windowIsFloating || windowDisableStarting) {
+                return false;
+            }
+            if (windowShowWallpaper) {
+                if (getDisplayContent().mWallpaperController
+                        .getWallpaperTarget() == null) {
+                    // If this theme is requesting a wallpaper, and the wallpaper
+                    // is not currently visible, then this effectively serves as
+                    // an opaque window and our starting window transition animation
+                    // can still work.  We just need to make sure the starting window
+                    // is also showing the wallpaper.
+                    windowFlags |= FLAG_SHOW_WALLPAPER;
+                } else {
+                    return false;
+                }
+            }
+        }
+
+        if (transferStartingWindow(transferFrom)) {
+            return true;
+        }
+
+        // There is no existing starting window, and we don't want to create a splash screen, so
+        // that's it!
+        if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
+            return false;
+        }
+
+        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
+        mStartingData = new SplashScreenStartingData(mWmService, pkg,
+                theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
+                getMergedOverrideConfiguration());
+        scheduleAddStartingWindow();
+        return true;
+    }
+
+    private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
+        if (snapshot == null) {
+            return false;
+        }
+
+        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
+        mStartingData = new SnapshotStartingData(mWmService, snapshot);
+        scheduleAddStartingWindow();
+        return true;
+    }
+
+    void scheduleAddStartingWindow() {
+        // Note: we really want to do sendMessageAtFrontOfQueue() because we
+        // want to process the message ASAP, before any other queued
+        // messages.
+        if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Enqueueing ADD_STARTING");
+            mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
+        }
+    }
+
+    private class AddStartingWindow implements Runnable {
+
+        @Override
+        public void run() {
+            // Can be accessed without holding the global lock
+            final StartingData startingData;
+            synchronized (mWmService.mGlobalLock) {
+                // There can only be one adding request, silly caller!
+                mWmService.mAnimationHandler.removeCallbacks(this);
+
+                if (mStartingData == null) {
+                    // Animation has been canceled... do nothing.
+                    ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
+                            "startingData was nulled out before handling"
+                                    + " mAddStartingWindow: %s", ActivityRecord.this);
+                    return;
+                }
+                startingData = mStartingData;
+            }
+
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Add starting %s: startingData=%s",
+                    this, startingData);
+
+
+            WindowManagerPolicy.StartingSurface surface = null;
+            try {
+                surface = startingData.createStartingSurface(ActivityRecord.this);
+            } catch (Exception e) {
+                Slog.w(TAG, "Exception when adding starting window", e);
+            }
+            if (surface != null) {
+                boolean abort = false;
+                synchronized (mWmService.mGlobalLock) {
+                    // If the window was successfully added, then
+                    // we need to remove it.
+                    if (removed || mStartingData == null) {
+                        ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
+                                "Aborted starting %s: removed=%b startingData=%s",
+                                ActivityRecord.this, removed, mStartingData);
+
+                        startingWindow = null;
+                        mStartingData = null;
+                        abort = true;
+                    } else {
+                        startingSurface = surface;
+                    }
+                    if (!abort) {
+                        ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
+                                "Added starting %s: startingWindow=%s startingView=%s",
+                                ActivityRecord.this, startingWindow, startingSurface);
+                    }
+                }
+                if (abort) {
+                    surface.remove();
+                }
+            } else {
+                ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Surface returned was null: %s",
+                        ActivityRecord.this);
+            }
+        }
+    }
+
+    private final AddStartingWindow mAddStartingWindow = new AddStartingWindow();
+
+    private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
+            boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
+            ActivityManager.TaskSnapshot snapshot) {
+        if (getDisplayContent().mAppTransition.getAppTransition()
+                == TRANSIT_DOCK_TASK_FROM_RECENTS) {
+            // TODO(b/34099271): Remove this statement to add back the starting window and figure
+            // out why it causes flickering, the starting window appears over the thumbnail while
+            // the docked from recents transition occurs
+            return STARTING_WINDOW_TYPE_NONE;
+        } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
+            return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+        } else if (taskSwitch && allowTaskSnapshot) {
+            if (mWmService.mLowRamTaskSnapshotsAndRecents) {
+                // For low RAM devices, we use the splash screen starting window instead of the
+                // task snapshot starting window.
+                return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+            }
+            return snapshot == null ? STARTING_WINDOW_TYPE_NONE
+                    : snapshotOrientationSameAsTask(snapshot) || fromRecents
+                            ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+        } else {
+            return STARTING_WINDOW_TYPE_NONE;
+        }
+    }
+
+    private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
+        if (snapshot == null) {
+            return false;
+        }
+        return getTask().getConfiguration().orientation == snapshot.getOrientation();
+    }
+
+    void removeStartingWindow() {
+        if (startingWindow == null) {
+            if (mStartingData != null) {
+                // Starting window has not been added yet, but it is scheduled to be added.
+                // Go ahead and cancel the request.
+                ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Clearing startingData for token=%s", this);
+                mStartingData = null;
+            }
+            return;
+        }
+
+        final WindowManagerPolicy.StartingSurface surface;
+        if (mStartingData != null) {
+            surface = startingSurface;
+            mStartingData = null;
+            startingSurface = null;
+            startingWindow = null;
+            startingDisplayed = false;
+            if (surface == null) {
+                ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
+                        "startingWindow was set but startingSurface==null, couldn't "
+                                + "remove");
+
+                return;
+            }
+        } else {
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
+                    "Tried to remove starting window but startingWindow was null: %s",
+                    this);
+            return;
+        }
+
+        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
+                        + " startingView=%s Callers=%s",
+                this, startingWindow, startingSurface, Debug.getCallers(5));
+
+
+        // Use the same thread to remove the window as we used to add it, as otherwise we end up
+        // with things in the view hierarchy being called from different threads.
+        mWmService.mAnimationHandler.post(() -> {
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing startingView=%s", surface);
+            try {
+                surface.remove();
+            } catch (Exception e) {
+                Slog.w(TAG_WM, "Exception when removing starting window", e);
+            }
+        });
     }
 
     void removeWindowContainer() {
@@ -1146,7 +2006,44 @@
                     + " r=" + this + " (" + prevTask.getStackId() + ")");
         }
 
-        reparent(newTask.getTask(), position);
+        final Task task = newTask.getTask();
+        ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving app token=%s"
+                + " to task=%d at %d", this, task.mTaskId, position);
+
+        if (task == null) {
+            throw new IllegalArgumentException("reparent: could not find task");
+        }
+        final Task currentTask = getTask();
+        if (task == currentTask) {
+            throw new IllegalArgumentException(
+                    "window token=" + this + " already child of task=" + currentTask);
+        }
+
+        if (currentTask.mStack != task.mStack) {
+            throw new IllegalArgumentException(
+                    "window token=" + this + " current task=" + currentTask
+                            + " belongs to a different stack than " + task);
+        }
+
+        ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reParentWindowToken: removing window token=%s"
+                + " from task=%s"  , this, currentTask);
+        final DisplayContent prevDisplayContent = getDisplayContent();
+
+        mReparenting = true;
+
+        getParent().removeChild(this);
+        task.addChild(this, position);
+
+        mReparenting = false;
+
+        // Relayout display(s).
+        final DisplayContent displayContent = task.getDisplayContent();
+        displayContent.setLayoutNeeded();
+        if (prevDisplayContent != displayContent) {
+            onDisplayChanged(displayContent);
+            prevDisplayContent.setLayoutNeeded();
+        }
+        getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
 
         // Reparenting prevents informing the parent stack of activity removal in the case that
         // the new stack has the same parent. we must manually signal here if this is not the case.
@@ -1251,9 +2148,23 @@
         return stack != null ? stack.getDisplay() : null;
     }
 
+    @Override
+    boolean fillsParent() {
+        return occludesParent();
+    }
+
+    /** Returns true if this activity is opaque and fills the entire space of this task. */
+    boolean occludesParent() {
+        return mOccludesParent;
+    }
+
     boolean setOccludesParent(boolean occludesParent) {
-        final boolean changed = super.setOccludesParent(occludesParent);
-        if (changed) {
+        final boolean changed = occludesParent != mOccludesParent;
+        mOccludesParent = occludesParent;
+        setMainWindowOpaque(occludesParent);
+        mWmService.mWindowPlacerLocked.requestTraversal();
+
+        if (changed && task != null) {
             if (!occludesParent) {
                 getActivityStack().convertActivityToTranslucent(this);
             }
@@ -1269,6 +2180,15 @@
         return changed;
     }
 
+    void setMainWindowOpaque(boolean isOpaque) {
+        final WindowState win = findMainWindow();
+        if (win == null) {
+            return;
+        }
+        isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
+        win.mWinAnimator.setOpaqueLocked(isOpaque);
+    }
+
     void takeFromHistory() {
         if (inHistory) {
             inHistory = false;
@@ -1420,6 +2340,22 @@
     }
 
     /**
+     * Sets if this AWT is in the process of closing or entering PIP.
+     * {@link #mWillCloseOrEnterPip}}
+     */
+    void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
+        mWillCloseOrEnterPip = willCloseOrEnterPip;
+    }
+
+    /**
+     * Returns whether this AWT is considered closing. Conditions are either
+     * 1. Is this app animating and was requested to be hidden
+     * 2. App is delayed closing since it might enter PIP.
+     */
+    boolean isClosingOrEnteringPip() {
+        return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
+    }
+    /**
      * @return Whether AppOps allows this package to enter picture-in-picture.
      */
     private boolean checkEnterPictureInPictureAppOpsState() {
@@ -1427,6 +2363,27 @@
                 OP_PICTURE_IN_PICTURE, info.applicationInfo.uid, packageName) == MODE_ALLOWED;
     }
 
+    boolean isAlwaysFocusable() {
+        return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
+    }
+
+    // TODO: Does this really need to be different from isAlwaysFocusable()? For the activity side
+    // focusable means resumeable. I guess with that in mind maybe we should rename the other
+    // method to isResumeable() or something like that.
+    boolean windowsAreFocusable() {
+        if (mTargetSdk < Build.VERSION_CODES.Q) {
+            final int pid = getPid();
+            final ActivityRecord topFocusedAppOfMyProcess =
+                    mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
+            if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
+                // For the apps below Q, there can be only one app which has the focused window per
+                // process, because legacy apps may not be ready for a multi-focus system.
+                return false;
+            }
+        }
+        return getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable();
+    }
+
     /** Move activity with its stack to front and make the stack focused. */
     boolean moveFocusableActivityToTop(String reason) {
         if (!isFocusable()) {
@@ -1577,12 +2534,12 @@
                     task.mTaskId, shortComponentName, reason);
             final ArrayList<ActivityRecord> activities = task.mActivities;
             final int index = activities.indexOf(this);
-            if (index < (activities.size() - 1)) {
+            if (index < (task.getChildCount() - 1)) {
                 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
                     // If the caller asked that this activity (and all above it)
                     // be cleared when the task is reset, don't lose that information,
                     // but propagate it up to the next activity.
-                    final ActivityRecord next = activities.get(index + 1);
+                    final ActivityRecord next = task.getChildAt(index + 1);
                     next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
                 }
             }
@@ -2004,10 +2961,6 @@
         if (stopped) {
             clearOptionsLocked();
         }
-
-        if (mAtmService != null) {
-            mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
-        }
     }
 
     /**
@@ -2079,6 +3032,106 @@
         clearRelaunching();
     }
 
+    boolean isRelaunching() {
+        return mPendingRelaunchCount > 0;
+    }
+
+    boolean shouldFreezeBounds() {
+        final Task task = getTask();
+
+        // For freeform windows, we can't freeze the bounds at the moment because this would make
+        // the resizing unresponsive.
+        if (task == null || task.inFreeformWindowingMode()) {
+            return false;
+        }
+
+        // We freeze the bounds while drag resizing to deal with the time between
+        // the divider/drag handle being released, and the handling it's new
+        // configuration. If we are relaunched outside of the drag resizing state,
+        // we need to be careful not to do this.
+        return getTask().isDragResizing();
+    }
+
+    void startRelaunching() {
+        if (shouldFreezeBounds()) {
+            freezeBounds();
+        }
+
+        // In the process of tearing down before relaunching, the app will
+        // try and clean up it's child surfaces. We need to prevent this from
+        // happening, so we sever the children, transfering their ownership
+        // from the client it-self to the parent surface (owned by us).
+        detachChildren();
+
+        mPendingRelaunchCount++;
+    }
+
+    /**
+     * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
+     * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
+     * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
+     * with a queue.
+     */
+    private void freezeBounds() {
+        final Task task = getTask();
+        mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
+
+        if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
+            // We didn't call prepareFreezingBounds on the task, so use the current value.
+            mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
+        } else {
+            mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
+        }
+        // Calling unset() to make it equal to Configuration.EMPTY.
+        task.mPreparedFrozenMergedConfig.unset();
+    }
+
+    void detachChildren() {
+        SurfaceControl.openTransaction();
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            w.mWinAnimator.detachChildren();
+        }
+        SurfaceControl.closeTransaction();
+    }
+
+    void finishRelaunching() {
+        unfreezeBounds();
+
+        if (mPendingRelaunchCount > 0) {
+            mPendingRelaunchCount--;
+        } else {
+            // Update keyguard flags upon finishing relaunch.
+            checkKeyguardFlagsChanged();
+        }
+    }
+
+    void clearRelaunching() {
+        if (mPendingRelaunchCount == 0) {
+            return;
+        }
+        unfreezeBounds();
+        mPendingRelaunchCount = 0;
+    }
+
+    /**
+     * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
+     */
+    private void unfreezeBounds() {
+        if (mFrozenBounds.isEmpty()) {
+            return;
+        }
+        mFrozenBounds.remove();
+        if (!mFrozenMergedConfig.isEmpty()) {
+            mFrozenMergedConfig.remove();
+        }
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = mChildren.get(i);
+            win.onUnfreezeBounds();
+        }
+        mWmService.mWindowPlacerLocked.performSurfacePlacement();
+    }
+
     /**
      * Perform clean-up of service connections in an activity record.
      */
@@ -2090,6 +3143,504 @@
         mServiceConnectionsHolder.disconnectActivityFromServices();
     }
 
+    @Override
+    void removeImmediately() {
+        onRemovedFromDisplay();
+        super.removeImmediately();
+    }
+
+    @Override
+    void removeIfPossible() {
+        mIsExiting = false;
+        removeAllWindowsIfPossible();
+        removeImmediately();
+    }
+
+    @Override
+    boolean checkCompleteDeferredRemoval() {
+        if (mIsExiting) {
+            removeIfPossible();
+        }
+        return super.checkCompleteDeferredRemoval();
+    }
+
+    void onRemovedFromDisplay() {
+        if (mRemovingFromDisplay) {
+            return;
+        }
+        mRemovingFromDisplay = true;
+
+        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this);
+
+        boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
+
+        getDisplayContent().mOpeningApps.remove(this);
+        getDisplayContent().mChangingApps.remove(this);
+        getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
+        mWmService.mTaskSnapshotController.onAppRemoved(this);
+        waitingToShow = false;
+        if (getDisplayContent().mClosingApps.contains(this)) {
+            delayed = true;
+        } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
+            getDisplayContent().mClosingApps.add(this);
+            delayed = true;
+        }
+
+        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
+                "Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
+                getAnimation(), isSelfAnimating());
+
+        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
+                + " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
+
+        if (mStartingData != null) {
+            removeStartingWindow();
+        }
+
+        // If this window was animating, then we need to ensure that the app transition notifies
+        // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
+        // so add to that list now
+        if (isSelfAnimating()) {
+            getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
+        }
+
+        final TaskStack stack = getStack();
+        if (delayed && !isEmpty()) {
+            // set the token aside because it has an active animation to be finished
+            ProtoLog.v(WM_DEBUG_ADD_REMOVE,
+                    "removeAppToken make exiting: %s", this);
+            if (stack != null) {
+                stack.mExitingActivities.add(this);
+            }
+            mIsExiting = true;
+        } else {
+            // Make sure there is no animation running on this token, so any windows associated
+            // with it will be removed as soon as their animations are complete
+            cancelAnimation();
+            if (stack != null) {
+                stack.mExitingActivities.remove(this);
+            }
+            removeIfPossible();
+        }
+
+        removed = true;
+        stopFreezingScreen(true, true);
+
+        final DisplayContent dc = getDisplayContent();
+        if (dc.mFocusedApp == this) {
+            ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
+                    "Removing focused app token:%s displayId=%d", this,
+                    dc.getDisplayId());
+            dc.setFocusedApp(null);
+            mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
+        }
+        if (mLetterbox != null) {
+            mLetterbox.destroy();
+            mLetterbox = null;
+        }
+
+        if (!delayed) {
+            updateReportedVisibilityLocked();
+        }
+
+        // Reset the last saved PiP snap fraction on removal.
+        mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
+
+        mRemovingFromDisplay = false;
+    }
+
+    /**
+     * Returns true if the new child window we are adding to this token is considered greater than
+     * the existing child window in this token in terms of z-order.
+     */
+    @Override
+    protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
+            WindowState existingWindow) {
+        final int type1 = newWindow.mAttrs.type;
+        final int type2 = existingWindow.mAttrs.type;
+
+        // Base application windows should be z-ordered BELOW all other windows in the app token.
+        if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
+            return false;
+        } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
+            return true;
+        }
+
+        // Starting windows should be z-ordered ABOVE all other windows in the app token.
+        if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
+            return true;
+        } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
+            return false;
+        }
+
+        // Otherwise the new window is greater than the existing window.
+        return true;
+    }
+
+    /**
+     * @return {@code true} if starting window is in app's hierarchy.
+     */
+    boolean hasStartingWindow() {
+        if (startingDisplayed || mStartingData != null) {
+            return true;
+        }
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean isLastWindow(WindowState win) {
+        return mChildren.size() == 1 && mChildren.get(0) == win;
+    }
+
+    @Override
+    void addWindow(WindowState w) {
+        super.addWindow(w);
+
+        boolean gotReplacementWindow = false;
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState candidate = mChildren.get(i);
+            gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
+        }
+
+        // if we got a replacement window, reset the timeout to give drawing more time
+        if (gotReplacementWindow) {
+            mWmService.scheduleWindowReplacementTimeouts(this);
+        }
+        checkKeyguardFlagsChanged();
+    }
+
+    @Override
+    void removeChild(WindowState child) {
+        if (!mChildren.contains(child)) {
+            // This can be true when testing.
+            return;
+        }
+        super.removeChild(child);
+        checkKeyguardFlagsChanged();
+        updateLetterboxSurface(child);
+    }
+
+    private boolean waitingForReplacement() {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState candidate = mChildren.get(i);
+            if (candidate.waitingForReplacement()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void onWindowReplacementTimeout() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            (mChildren.get(i)).onWindowReplacementTimeout();
+        }
+    }
+
+    void setAppLayoutChanges(int changes, String reason) {
+        if (!mChildren.isEmpty()) {
+            final DisplayContent dc = getDisplayContent();
+            dc.pendingLayoutChanges |= changes;
+            if (DEBUG_LAYOUT_REPEATS) {
+                mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
+            }
+        }
+    }
+
+    void removeReplacedWindowIfNeeded(WindowState replacement) {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = mChildren.get(i);
+            if (win.removeReplacedWindowIfNeeded(replacement)) {
+                return;
+            }
+        }
+    }
+
+    boolean transferStartingWindow(IBinder transferFrom) {
+        final ActivityRecord fromActivity = getDisplayContent().getActivityRecord(transferFrom);
+        if (fromActivity == null) {
+            return false;
+        }
+
+        final WindowState tStartingWindow = fromActivity.startingWindow;
+        if (tStartingWindow != null && fromActivity.startingSurface != null) {
+            // In this case, the starting icon has already been displayed, so start
+            // letting windows get shown immediately without any more transitions.
+            getDisplayContent().mSkipAppTransitionAnimation = true;
+
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Moving existing starting %s"
+                    + " from %s to %s", tStartingWindow, fromActivity, this);
+
+            final long origId = Binder.clearCallingIdentity();
+            try {
+                // Transfer the starting window over to the new token.
+                mStartingData = fromActivity.mStartingData;
+                startingSurface = fromActivity.startingSurface;
+                startingDisplayed = fromActivity.startingDisplayed;
+                fromActivity.startingDisplayed = false;
+                startingWindow = tStartingWindow;
+                reportedVisible = fromActivity.reportedVisible;
+                fromActivity.mStartingData = null;
+                fromActivity.startingSurface = null;
+                fromActivity.startingWindow = null;
+                fromActivity.startingMoved = true;
+                tStartingWindow.mToken = this;
+                tStartingWindow.mActivityRecord = this;
+
+                ProtoLog.v(WM_DEBUG_ADD_REMOVE,
+                        "Removing starting %s from %s", tStartingWindow, fromActivity);
+                fromActivity.removeChild(tStartingWindow);
+                fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow);
+                fromActivity.mHiddenSetFromTransferredStartingWindow = false;
+                addWindow(tStartingWindow);
+
+                // Propagate other interesting state between the tokens. If the old token is displayed,
+                // we should immediately force the new one to be displayed. If it is animating, we need
+                // to move that animation to the new one.
+                if (fromActivity.allDrawn) {
+                    allDrawn = true;
+                    deferClearAllDrawn = fromActivity.deferClearAllDrawn;
+                }
+                if (fromActivity.firstWindowDrawn) {
+                    firstWindowDrawn = true;
+                }
+                if (!fromActivity.isHidden()) {
+                    setHidden(false);
+                    hiddenRequested = false;
+                    mHiddenSetFromTransferredStartingWindow = true;
+                }
+                setClientHidden(fromActivity.mClientHidden);
+
+                transferAnimation(fromActivity);
+
+                // When transferring an animation, we no longer need to apply an animation to the
+                // the token we transfer the animation over. Thus, set this flag to indicate we've
+                // transferred the animation.
+                mUseTransferredAnimation = true;
+
+                mWmService.updateFocusedWindowLocked(
+                        UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
+                getDisplayContent().setLayoutNeeded();
+                mWmService.mWindowPlacerLocked.performSurfacePlacement();
+            } finally {
+                Binder.restoreCallingIdentity(origId);
+            }
+            return true;
+        } else if (fromActivity.mStartingData != null) {
+            // The previous app was getting ready to show a
+            // starting window, but hasn't yet done so.  Steal it!
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
+                    "Moving pending starting from %s to %s", fromActivity, this);
+            mStartingData = fromActivity.mStartingData;
+            fromActivity.mStartingData = null;
+            fromActivity.startingMoved = true;
+            scheduleAddStartingWindow();
+            return true;
+        }
+
+        // TODO: Transfer thumbnail
+
+        return false;
+    }
+
+    /**
+     * Tries to transfer the starting window from a token that's above ourselves in the task but
+     * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
+     * activity M in the same task. Now, when reopening the task, T starts on top of M but then
+     * immediately finishes after, so we have to transfer T to M.
+     */
+    void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
+        final Task task = getTask();
+        for (int i = task.mChildren.size() - 1; i >= 0; i--) {
+            final ActivityRecord fromActivity = task.mChildren.get(i);
+            if (fromActivity == this) {
+                return;
+            }
+            if (fromActivity.hiddenRequested && transferStartingWindow(fromActivity.token)) {
+                return;
+            }
+        }
+    }
+
+    void checkKeyguardFlagsChanged() {
+        final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
+        final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
+        if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
+                || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
+            mWmService.notifyKeyguardFlagsChanged(null /* callback */,
+                    getDisplayContent().getDisplayId());
+        }
+        mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
+        mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
+    }
+
+    boolean containsDismissKeyguardWindow() {
+        // Window state is transient during relaunch. We are not guaranteed to be frozen during the
+        // entirety of the relaunch.
+        if (isRelaunching()) {
+            return mLastContainsDismissKeyguardWindow;
+        }
+
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean containsShowWhenLockedWindow() {
+        // When we are relaunching, it is possible for us to be unfrozen before our previous
+        // windows have been added back. Using the cached value ensures that our previous
+        // showWhenLocked preference is honored until relaunching is complete.
+        if (isRelaunching()) {
+            return mLastContainsShowWhenLockedWindow;
+        }
+
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    void setShowWhenLocked(boolean showWhenLocked) {
+        mShowWhenLocked = showWhenLocked;
+        mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
+                0 /* configChanges */, false /* preserveWindows */);
+    }
+
+    void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
+        mInheritShownWhenLocked = inheritShowWhenLocked;
+        mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
+                0 /* configChanges */, false /* preserveWindows */);
+    }
+
+    /**
+     * @return {@code true} if the activity windowing mode is not
+     *         {@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
+     *         {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
+     *         conditions a) above.
+     *         Multi-windowing mode will be exited if {@code true} is returned.
+     */
+    boolean canShowWhenLocked() {
+        if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
+            return true;
+        } else if (mInheritShownWhenLocked) {
+            final ActivityRecord r = getActivityBelow();
+            return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
+                    || r.containsShowWhenLockedWindow());
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * @return Whether we are allowed to show non-starting windows at the moment. We disallow
+     *         showing windows during transitions in case we have windows that have wide-color-gamut
+     *         color mode set to avoid jank in the middle of the transition.
+     */
+    boolean canShowWindows() {
+        return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
+    }
+
+    /**
+     * @return true if we have a window that has a non-default color mode set; false otherwise.
+     */
+    private boolean hasNonDefaultColorWindow() {
+        return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
+                true /* topToBottom */);
+    }
+
+    /**
+     * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
+     * such activity exists.
+     */
+    @Nullable
+    private ActivityRecord getActivityBelow() {
+        final Task task = getTask();
+        final int pos = task.mChildren.indexOf(this);
+        if (pos == -1) {
+            throw new IllegalStateException("Activity not found in its task");
+        }
+        return pos == 0 ? null : task.getChildAt(pos - 1);
+    }
+
+    WindowState getImeTargetBelowWindow(WindowState w) {
+        final int index = mChildren.indexOf(w);
+        if (index > 0) {
+            final WindowState target = mChildren.get(index - 1);
+            if (target.canBeImeTarget()) {
+                return target;
+            }
+        }
+        return null;
+    }
+
+    WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
+        WindowState candidate = null;
+        for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            if (w.mRemoved) {
+                continue;
+            }
+            if (candidate == null) {
+                candidate = w;
+            }
+        }
+        return candidate;
+    }
+
+    @Override
+    boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
+        // For legacy reasons we process the TaskStack.mExitingActivities first in DisplayContent
+        // before the non-exiting app tokens. So, we skip the exiting app tokens here.
+        // TODO: Investigate if we need to continue to do this or if we can just process them
+        // in-order.
+        if (mIsExiting && !waitingForReplacement()) {
+            return false;
+        }
+        return forAllWindowsUnchecked(callback, traverseTopToBottom);
+    }
+
+    @Override
+    void forAllActivities(Consumer<ActivityRecord> callback) {
+        callback.accept(this);
+    }
+
+    boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
+            boolean traverseTopToBottom) {
+        return super.forAllWindows(callback, traverseTopToBottom);
+    }
+
+    @Override
+    protected void setLayer(Transaction t, int layer) {
+        if (!mSurfaceAnimator.hasLeash()) {
+            t.setLayer(mSurfaceControl, layer);
+        }
+    }
+
+    @Override
+    protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
+        if (!mSurfaceAnimator.hasLeash()) {
+            t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
+        }
+    }
+
+    @Override
+    protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
+        if (!mSurfaceAnimator.hasLeash()) {
+            t.reparent(mSurfaceControl, newParent);
+        }
+    }
+
     void logStartActivity(int tag, TaskRecord task) {
         final Uri data = intent.getData();
         final String strData = data != null ? data.toSafeString() : null;
@@ -2334,6 +3885,65 @@
         }
     }
 
+    void clearAllDrawn() {
+        allDrawn = false;
+        deferClearAllDrawn = false;
+    }
+
+    /**
+     * Returns whether the drawn window states of this {@link ActivityRecord} has considered every
+     * child {@link WindowState}. A child is considered if it has been passed into
+     * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
+     * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
+     * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
+     *
+     * @return {@code true} If all children have been considered, {@code false}.
+     */
+    private boolean allDrawnStatesConsidered() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState child = mChildren.get(i);
+            if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     *  Determines if the token has finished drawing. This should only be called from
+     *  {@link DisplayContent#applySurfaceChangesTransaction}
+     */
+    void updateAllDrawn() {
+        if (!allDrawn) {
+            // Number of drawn windows can be less when a window is being relaunched, wait for
+            // all windows to be launched and drawn for this token be considered all drawn.
+            final int numInteresting = mNumInterestingWindows;
+
+            // We must make sure that all present children have been considered (determined by
+            // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
+            // drawn.
+            if (numInteresting > 0 && allDrawnStatesConsidered()
+                    && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
+                if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
+                        + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
+                allDrawn = true;
+                // Force an additional layout pass where
+                // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
+                if (mDisplayContent != null) {
+                    mDisplayContent.setLayoutNeeded();
+                }
+                mWmService.mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
+
+                // Notify the pinned stack upon all windows drawn. If there was an animation in
+                // progress then this signal will resume that animation.
+                final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
+                if (pinnedStack != null) {
+                    pinnedStack.onAllWindowsDrawn();
+                }
+            }
+        }
+    }
+
     ActivityOptions getOptionsForTargetActivityLocked() {
         return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
     }
@@ -2408,6 +4018,13 @@
         }
     }
 
+    @Override
+    boolean isVisible() {
+        // If the activity isn't hidden then it is considered visible and there is no need to check
+        // its children windows to see if they are visible.
+        return !isHidden();
+    }
+
     void setVisibility(boolean visible) {
         if (getParent() == null) {
             Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
@@ -2428,6 +4045,336 @@
         mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
     }
 
+    void setVisibility(boolean visible, boolean deferHidingClient) {
+        final AppTransition appTransition = getDisplayContent().mAppTransition;
+
+        // Don't set visibility to false if we were already not visible. This prevents WM from
+        // adding the app to the closing app list which doesn't make sense for something that is
+        // already not visible. However, set visibility to true even if we are already visible.
+        // This makes sure the app is added to the opening apps list so that the right
+        // transition can be selected.
+        // TODO: Probably a good idea to separate the concept of opening/closing apps from the
+        // concept of setting visibility...
+        if (!visible && hiddenRequested) {
+
+            if (!deferHidingClient && mLastDeferHidingClient) {
+                // We previously deferred telling the client to hide itself when visibility was
+                // initially set to false. Now we would like it to hide, so go ahead and set it.
+                mLastDeferHidingClient = deferHidingClient;
+                setClientHidden(true);
+            }
+            return;
+        }
+
+        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
+                "setAppVisibility(%s, visible=%b): %s hidden=%b hiddenRequested=%b Callers=%s",
+                appToken, visible, appTransition, isHidden(), hiddenRequested,
+                Debug.getCallers(6));
+
+        final DisplayContent displayContent = getDisplayContent();
+        displayContent.mOpeningApps.remove(this);
+        displayContent.mClosingApps.remove(this);
+        if (isInChangeTransition()) {
+            clearChangeLeash(getPendingTransaction(), true /* cancel */);
+        }
+        displayContent.mChangingApps.remove(this);
+        waitingToShow = false;
+        hiddenRequested = !visible;
+        mLastDeferHidingClient = deferHidingClient;
+
+        if (!visible) {
+            // If the app is dead while it was visible, we kept its dead window on screen.
+            // Now that the app is going invisible, we can remove it. It will be restarted
+            // if made visible again.
+            removeDeadWindows();
+        } else {
+            if (!appTransition.isTransitionSet()
+                    && appTransition.isReady()) {
+                // Add the app mOpeningApps if transition is unset but ready. This means
+                // we're doing a screen freeze, and the unfreeze will wait for all opening
+                // apps to be ready.
+                displayContent.mOpeningApps.add(this);
+            }
+            startingMoved = false;
+            // If the token is currently hidden (should be the common case), or has been
+            // stopped, then we need to set up to wait for its windows to be ready.
+            if (isHidden() || mAppStopped) {
+                clearAllDrawn();
+
+                // If the app was already visible, don't reset the waitingToShow state.
+                if (isHidden()) {
+                    waitingToShow = true;
+
+                    // If the client isn't hidden, we don't need to reset the drawing state.
+                    if (isClientHidden()) {
+                        // Let's reset the draw state in order to prevent the starting window to be
+                        // immediately dismissed when the app still has the surface.
+                        forAllWindows(w -> {
+                            if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
+                                w.mWinAnimator.resetDrawState();
+
+                                // Force add to mResizingWindows, so that we are guaranteed to get
+                                // another reportDrawn callback.
+                                w.resetLastContentInsets();
+                            }
+                        }, true /* traverseTopToBottom */);
+                    }
+                }
+            }
+
+            // In the case where we are making an app visible but holding off for a transition,
+            // we still need to tell the client to make its windows visible so they get drawn.
+            // Otherwise, we will wait on performing the transition until all windows have been
+            // drawn, they never will be, and we are sad.
+            setClientHidden(false);
+
+            requestUpdateWallpaperIfNeeded();
+
+            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "No longer Stopped: %s", this);
+            mAppStopped = false;
+
+            transferStartingWindowFromHiddenAboveTokenIfNeeded();
+        }
+
+        // If we are preparing an app transition, then delay changing
+        // the visibility of this token until we execute that transition.
+        if (okToAnimate() && appTransition.isTransitionSet()) {
+            inPendingTransaction = true;
+            if (visible) {
+                displayContent.mOpeningApps.add(this);
+                mEnteringAnimation = true;
+            } else {
+                displayContent.mClosingApps.add(this);
+                mEnteringAnimation = false;
+            }
+            if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
+                // We're launchingBehind, add the launching activity to mOpeningApps.
+                final WindowState win = getDisplayContent().findFocusedWindow();
+                if (win != null) {
+                    final ActivityRecord focusedActivity = win.mActivityRecord;
+                    if (focusedActivity != null) {
+                        ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
+                                "TRANSIT_TASK_OPEN_BEHIND,  adding %s to mOpeningApps",
+                                focusedActivity);
+
+                        // Force animation to be loaded.
+                        displayContent.mOpeningApps.add(focusedActivity);
+                    }
+                }
+            }
+            return;
+        }
+
+        commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
+        updateReportedVisibilityLocked();
+    }
+
+    boolean commitVisibility(WindowManager.LayoutParams lp,
+            boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
+
+        boolean delayed = false;
+        inPendingTransaction = false;
+        // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
+        // been set by the app now.
+        mHiddenSetFromTransferredStartingWindow = false;
+
+        // Allow for state changes and animation to be applied if:
+        // * token is transitioning visibility state
+        // * or the token was marked as hidden and is exiting before we had a chance to play the
+        // transition animation
+        // * or this is an opening app and windows are being replaced
+        // * or the token is the opening app and visible while opening task behind existing one.
+        final DisplayContent displayContent = getDisplayContent();
+        boolean visibilityChanged = false;
+        if (isHidden() == visible || (isHidden() && mIsExiting)
+                || (visible && waitingForReplacement())
+                || (visible && displayContent.mOpeningApps.contains(this)
+                && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) {
+            final AccessibilityController accessibilityController =
+                    mWmService.mAccessibilityController;
+            boolean changed = false;
+            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
+                    "Changing app %s hidden=%b performLayout=%b", this, isHidden(),
+                    performLayout);
+
+            boolean runningAppAnimation = false;
+
+            if (transit != WindowManager.TRANSIT_UNSET) {
+                if (mUseTransferredAnimation) {
+                    runningAppAnimation = isReallyAnimating();
+                } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
+                    runningAppAnimation = true;
+                }
+                delayed = runningAppAnimation;
+                final WindowState window = findMainWindow();
+                if (window != null && accessibilityController != null) {
+                    accessibilityController.onAppWindowTransitionLocked(window, transit);
+                }
+                changed = true;
+            }
+
+            final int windowsCount = mChildren.size();
+            for (int i = 0; i < windowsCount; i++) {
+                final WindowState win = mChildren.get(i);
+                changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
+            }
+
+            setHidden(!visible);
+            hiddenRequested = !visible;
+            visibilityChanged = true;
+            if (!visible) {
+                stopFreezingScreen(true, true);
+            } else {
+                // If we are being set visible, and the starting window is not yet displayed,
+                // then make sure it doesn't get displayed.
+                if (startingWindow != null && !startingWindow.isDrawnLw()) {
+                    startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
+                    startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
+                }
+
+                // We are becoming visible, so better freeze the screen with the windows that are
+                // getting visible so we also wait for them.
+                forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
+            }
+
+            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
+                    "commitVisibility: %s: hidden=%b hiddenRequested=%b", this,
+                    isHidden(), hiddenRequested);
+
+            if (changed) {
+                displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
+                if (performLayout) {
+                    mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                            false /*updateInputWindows*/);
+                    mWmService.mWindowPlacerLocked.performSurfacePlacement();
+                }
+                displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
+            }
+        }
+        mUseTransferredAnimation = false;
+
+        if (isReallyAnimating()) {
+            delayed = true;
+        } else {
+            // We aren't animating anything, but exiting windows rely on the animation finished
+            // callback being called in case the ActivityRecord was pretending to be animating,
+            // which we might have done because we were in closing/opening apps list.
+            onAnimationFinished();
+        }
+
+        for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
+            if ((mChildren.get(i)).isSelfOrChildAnimating()) {
+                delayed = true;
+            }
+        }
+
+        if (visibilityChanged) {
+            if (visible && !delayed) {
+                // The token was made immediately visible, there will be no entrance animation.
+                // We need to inform the client the enter animation was finished.
+                mEnteringAnimation = true;
+                mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
+                        token);
+            }
+
+            // If we're becoming visible, immediately change client visibility as well. there seem
+            // to be some edge cases where we change our visibility but client visibility never gets
+            // updated.
+            // If we're becoming invisible, update the client visibility if we are not running an
+            // animation. Otherwise, we'll update client visibility in onAnimationFinished.
+            if (visible || !isReallyAnimating()) {
+                setClientHidden(!visible);
+            }
+
+            if (!displayContent.mClosingApps.contains(this)
+                    && !displayContent.mOpeningApps.contains(this)) {
+                // The token is not closing nor opening, so even if there is an animation set, that
+                // doesn't mean that it goes through the normal app transition cycle so we have
+                // to inform the docked controller about visibility change.
+                // TODO(multi-display): notify docked divider on all displays where visibility was
+                // affected.
+                displayContent.getDockedDividerController().notifyAppVisibilityChanged();
+
+                // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
+                // will not be taken.
+                mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
+            }
+
+            // If we are hidden but there is no delay needed we immediately
+            // apply the Surface transaction so that the ActivityManager
+            // can have some guarantee on the Surface state following
+            // setting the visibility. This captures cases like dismissing
+            // the docked or pinned stack where there is no app transition.
+            //
+            // In the case of a "Null" animation, there will be
+            // no animation but there will still be a transition set.
+            // We still need to delay hiding the surface such that it
+            // can be synchronized with showing the next surface in the transition.
+            if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
+                SurfaceControl.openTransaction();
+                for (int i = mChildren.size() - 1; i >= 0; i--) {
+                    mChildren.get(i).mWinAnimator.hide("immediately hidden");
+                }
+                SurfaceControl.closeTransaction();
+            }
+        }
+
+        return delayed;
+    }
+
+    @Override
+    void setHidden(boolean hidden) {
+        super.setHidden(hidden);
+        scheduleAnimation();
+    }
+
+    @Override
+    void onAppTransitionDone() {
+        sendingToBottom = false;
+    }
+
+    /**
+     * See {@link Activity#setDisablePreviewScreenshots}.
+     */
+    void setDisablePreviewScreenshots(boolean disable) {
+        mDisablePreviewScreenshots = disable;
+    }
+
+    /**
+     * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
+     * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
+     * we can't take a snapshot for other reasons, for example, if we have a secure window.
+     *
+     * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
+     *         screenshot.
+     */
+    boolean shouldUseAppThemeSnapshot() {
+        return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
+                true /* topToBottom */);
+    }
+
+    /**
+     * Sets whether the current launch can turn the screen on.
+     * @see #currentLaunchCanTurnScreenOn()
+     */
+    void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
+        mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
+    }
+
+    /**
+     * Indicates whether the current launch can turn the screen on. This is to prevent multiple
+     * relayouts from turning the screen back on. The screen should only turn on at most
+     * once per activity resume.
+     * <p>
+     * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
+     * or {@link ActivityRecord#canTurnScreenOn} is set.
+     *
+     * @return {@code true} if the activity is ready to turn on the screen.
+     */
+    boolean currentLaunchCanTurnScreenOn() {
+        return mCurrentLaunchCanTurnScreenOn;
+    }
+
     void setState(ActivityState state, String reason) {
         if (DEBUG_STATES) Slog.v(TAG_STATES, "State movement: " + this + " from:" + getState()
                         + " to:" + state + " reason:" + reason);
@@ -2513,13 +4460,63 @@
                 || state5 == mState;
     }
 
+    void destroySurfaces() {
+        destroySurfaces(false /*cleanupOnResume*/);
+    }
+
+    /**
+     * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
+     * the client has finished with them.
+     *
+     * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
+     * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
+     * others so that they are ready to be reused. If set to false (common case), destroy all
+     * surfaces that's eligible, if the app is already stopped.
+     */
+    private void destroySurfaces(boolean cleanupOnResume) {
+        boolean destroyedSomething = false;
+
+        // Copying to a different list as multiple children can be removed.
+        final ArrayList<WindowState> children = new ArrayList<>(mChildren);
+        for (int i = children.size() - 1; i >= 0; i--) {
+            final WindowState win = children.get(i);
+            destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
+        }
+        if (destroyedSomething) {
+            final DisplayContent dc = getDisplayContent();
+            dc.assignWindowLayers(true /*setLayoutNeeded*/);
+            updateLetterboxSurface(null);
+        }
+    }
+
     void notifyAppResumed(boolean wasStopped) {
         if (getParent() == null) {
             Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: "
                     + appToken);
             return;
         }
-        super.notifyAppResumed(wasStopped);
+        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppResumed: wasStopped=%b %s",
+                wasStopped, this);
+        mAppStopped = false;
+        // Allow the window to turn the screen on once the app is resumed again.
+        setCurrentLaunchCanTurnScreenOn(true);
+        if (!wasStopped) {
+            destroySurfaces(true /*cleanupOnResume*/);
+        }
+    }
+
+    /**
+     * Notify that the app has stopped, and it is okay to destroy any surfaces which were
+     * keeping alive in case they were still being used.
+     */
+    void notifyAppStopped() {
+        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
+        mAppStopped = true;
+        // Reset the last saved PiP snap fraction on app stop.
+        mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
+        destroySurfaces();
+        // Remove any starting window that was added for this app if they are still around.
+        removeStartingWindow();
     }
 
     void notifyUnknownVisibilityLaunched() {
@@ -2788,12 +4785,12 @@
         if (positionInTask == -1) {
             throw new IllegalStateException("Activity not found in its task");
         }
-        if (positionInTask == task.mActivities.size() - 1) {
+        if (positionInTask == task.getChildCount() - 1) {
             // It's the topmost activity in the task - should become resumed now
             return true;
         }
         // Check if activity above is finishing now and this one becomes the topmost in task.
-        final ActivityRecord activityAbove = task.mActivities.get(positionInTask + 1);
+        final ActivityRecord activityAbove = task.getChildAt(positionInTask + 1);
         if (activityAbove.finishing && results == null) {
             // We will only allow making active if activity above wasn't launched for result.
             // Otherwise it will cause this activity to resume before getting result.
@@ -2844,11 +4841,14 @@
         }
         idle = false;
         results = null;
+        if (newIntents != null && newIntents.size() > 0) {
+            mLastNewIntent = newIntents.get(newIntents.size() - 1);
+        }
         newIntents = null;
         stopped = false;
 
         if (isActivityTypeHome()) {
-            mStackSupervisor.updateHomeProcess(task.mActivities.get(0).app);
+            mStackSupervisor.updateHomeProcess(task.getChildAt(0).app);
         }
 
         if (nowVisible) {
@@ -3087,6 +5087,40 @@
         }
     }
 
+    void startFreezingScreen() {
+        ProtoLog.i(WM_DEBUG_ORIENTATION,
+                "Set freezing of %s: hidden=%b freezing=%b hiddenRequested=%b. %s",
+                appToken, isHidden(), mFreezingScreen, hiddenRequested,
+                new RuntimeException().fillInStackTrace());
+        if (!hiddenRequested) {
+            if (!mFreezingScreen) {
+                mFreezingScreen = true;
+                mWmService.registerAppFreezeListener(this);
+                mWmService.mAppsFreezingScreen++;
+                if (mWmService.mAppsFreezingScreen == 1) {
+                    mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
+                    mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
+                    mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
+                }
+            }
+            final int count = mChildren.size();
+            for (int i = 0; i < count; i++) {
+                final WindowState w = mChildren.get(i);
+                w.onStartFreezingScreen();
+            }
+        }
+    }
+
+    boolean isFreezingScreen() {
+        return mFreezingScreen;
+    }
+
+    @Override
+    public void onAppFreezeTimeout() {
+        Slog.w(TAG_WM, "Force clearing freeze: " + this);
+        stopFreezingScreen(true, true);
+    }
+
     void stopFreezingScreenLocked(boolean force) {
         if (force || frozenBeforeDestroy) {
             frozenBeforeDestroy = false;
@@ -3100,23 +5134,68 @@
         }
     }
 
+    void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
+        if (!mFreezingScreen) {
+            return;
+        }
+        ProtoLog.v(WM_DEBUG_ORIENTATION,
+                "Clear freezing of %s force=%b", this, force);
+        final int count = mChildren.size();
+        boolean unfrozeWindows = false;
+        for (int i = 0; i < count; i++) {
+            final WindowState w = mChildren.get(i);
+            unfrozeWindows |= w.onStopFreezingScreen();
+        }
+        if (force || unfrozeWindows) {
+            ProtoLog.v(WM_DEBUG_ORIENTATION, "No longer freezing: %s", this);
+            mFreezingScreen = false;
+            mWmService.unregisterAppFreezeListener(this);
+            mWmService.mAppsFreezingScreen--;
+            mWmService.mLastFinishedFreezeSource = this;
+        }
+        if (unfreezeSurfaceNow) {
+            if (unfrozeWindows) {
+                mWmService.mWindowPlacerLocked.performSurfacePlacement();
+            }
+            mWmService.stopFreezingDisplayLocked();
+        }
+    }
+
     void reportFullyDrawnLocked(boolean restoredFromBundle) {
         final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
-                .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
+            .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
         if (info != null) {
             mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
                     info.windowsFullyDrawnDelayMs, info.getLaunchState());
         }
     }
 
+    void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
+        firstWindowDrawn = true;
+
+        // We now have a good window to show, remove dead placeholders
+        removeDeadWindows();
+
+        if (startingWindow != null) {
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finish starting %s"
+                    + ": first real window is shown, no animation", win.mToken);
+            // If this initial window is animating, stop it -- we will do an animation to reveal
+            // it from behind the starting window, so there is no need for it to also be doing its
+            // own stuff.
+            win.cancelAnimation();
+        }
+        removeStartingWindow();
+        updateReportedVisibilityLocked();
+    }
+
     /** Called when the windows associated app window container are drawn. */
-    void onWindowsDrawn(boolean drawn, long timestamp) {
+    void onWindowsDrawn(boolean drawn, long timestampNs) {
         mDrawn = drawn;
         if (!drawn) {
             return;
         }
         final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
-                .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestamp);
+            .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestampNs);
         final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
         final @LaunchState int launchState = info != null ? info.getLaunchState() : -1;
         mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
@@ -3130,7 +5209,7 @@
 
     /** Called when the windows associated app window container are visible. */
     void onWindowsVisible() {
-        super.onWindowsVisible();
+        if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in " + appToken);
         mStackSupervisor.stopWaitingForActivityVisible(this);
         if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
         if (!nowVisible) {
@@ -3142,11 +5221,197 @@
 
     /** Called when the windows associated app window container are no longer visible. */
     void onWindowsGone() {
-        super.onWindowsGone();
+        if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in " + appToken);
         if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
         nowVisible = false;
     }
 
+    @Override
+    void checkAppWindowsReadyToShow() {
+        if (allDrawn == mLastAllDrawn) {
+            return;
+        }
+
+        mLastAllDrawn = allDrawn;
+        if (!allDrawn) {
+            return;
+        }
+
+        // The token has now changed state to having all windows shown...  what to do, what to do?
+        if (mFreezingScreen) {
+            showAllWindowsLocked();
+            stopFreezingScreen(false, true);
+            ProtoLog.i(WM_DEBUG_ORIENTATION,
+                    "Setting mOrientationChangeComplete=true because wtoken %s "
+                            + "numInteresting=%d numDrawn=%d",
+                    this, mNumInterestingWindows, mNumDrawnWindows);
+            // This will set mOrientationChangeComplete and cause a pass through layout.
+            setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
+                    "checkAppWindowsReadyToShow: freezingScreen");
+        } else {
+            setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
+
+            // We can now show all of the drawn windows!
+            if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
+                showAllWindowsLocked();
+            }
+        }
+    }
+
+    /**
+     * This must be called while inside a transaction.
+     */
+    void showAllWindowsLocked() {
+        forAllWindows(windowState -> {
+            if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
+            windowState.performShowLocked();
+        }, false /* traverseTopToBottom */);
+    }
+
+    void updateReportedVisibilityLocked() {
+        if (appToken == null) {
+            return;
+        }
+
+        if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
+        final int count = mChildren.size();
+
+        mReportedVisibilityResults.reset();
+
+        for (int i = 0; i < count; i++) {
+            final WindowState win = mChildren.get(i);
+            win.updateReportedVisibility(mReportedVisibilityResults);
+        }
+
+        int numInteresting = mReportedVisibilityResults.numInteresting;
+        int numVisible = mReportedVisibilityResults.numVisible;
+        int numDrawn = mReportedVisibilityResults.numDrawn;
+        boolean nowGone = mReportedVisibilityResults.nowGone;
+
+        boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
+        boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
+        if (!nowGone) {
+            // If the app is not yet gone, then it can only become visible/drawn.
+            if (!nowDrawn) {
+                nowDrawn = reportedDrawn;
+            }
+            if (!nowVisible) {
+                nowVisible = reportedVisible;
+            }
+        }
+        if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
+                + numInteresting + " visible=" + numVisible);
+        if (nowDrawn != reportedDrawn) {
+            onWindowsDrawn(nowDrawn, SystemClock.elapsedRealtimeNanos());
+            reportedDrawn = nowDrawn;
+        }
+        if (nowVisible != reportedVisible) {
+            if (DEBUG_VISIBILITY) Slog.v(TAG,
+                    "Visibility changed in " + this + ": vis=" + nowVisible);
+            reportedVisible = nowVisible;
+            if (nowVisible) {
+                onWindowsVisible();
+            } else {
+                onWindowsGone();
+            }
+        }
+    }
+
+    boolean isClientHidden() {
+        return mClientHidden;
+    }
+
+    void setClientHidden(boolean hideClient) {
+        if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
+            return;
+        }
+        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
+                "setClientHidden: %s clientHidden=%b Callers=%s", this, hideClient,
+                Debug.getCallers(5));
+        mClientHidden = hideClient;
+        sendAppVisibilityToClients();
+    }
+
+    /**
+     * Updated this app token tracking states for interesting and drawn windows based on the window.
+     *
+     * @return Returns true if the input window is considered interesting and drawn while all the
+     *         windows in this app token where not considered drawn as of the last pass.
+     */
+    boolean updateDrawnWindowStates(WindowState w) {
+        w.setDrawnStateEvaluated(true /*evaluated*/);
+
+        if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
+            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
+                    + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
+        }
+
+        if (allDrawn && !mFreezingScreen) {
+            return false;
+        }
+
+        if (mLastTransactionSequence != mWmService.mTransactionSequence) {
+            mLastTransactionSequence = mWmService.mTransactionSequence;
+            mNumDrawnWindows = 0;
+            startingDisplayed = false;
+
+            // There is the main base application window, even if it is exiting, wait for it
+            mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
+        }
+
+        final WindowStateAnimator winAnimator = w.mWinAnimator;
+
+        boolean isInterestingAndDrawn = false;
+
+        if (!allDrawn && w.mightAffectAllDrawn()) {
+            if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
+                Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
+                        + ", isAnimationSet=" + isSelfAnimating());
+                if (!w.isDrawnLw()) {
+                    Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
+                            + " pv=" + w.isVisibleByPolicy()
+                            + " mDrawState=" + winAnimator.drawStateToString()
+                            + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
+                            + " a=" + isSelfAnimating());
+                }
+            }
+
+            if (w != startingWindow) {
+                if (w.isInteresting()) {
+                    // Add non-main window as interesting since the main app has already been added
+                    if (findMainWindow(false /* includeStartingApp */) != w) {
+                        mNumInterestingWindows++;
+                    }
+                    if (w.isDrawnLw()) {
+                        mNumDrawnWindows++;
+
+                        if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
+                            Slog.v(TAG, "tokenMayBeDrawn: "
+                                    + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
+                                    + " freezingScreen=" + mFreezingScreen
+                                    + " mAppFreezing=" + w.mAppFreezing);
+                        }
+
+                        isInterestingAndDrawn = true;
+                    }
+                }
+            } else if (w.isDrawnLw()) {
+                onStartingWindowDrawn(SystemClock.uptimeMillis());
+                startingDisplayed = true;
+            }
+        }
+
+        return isInterestingAndDrawn;
+    }
+
+    /** Called when the starting window for this container is drawn. */
+    private void onStartingWindowDrawn(long timestamp) {
+        synchronized (mAtmService.mGlobalLock) {
+            mAtmService.mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
+                    getWindowingMode(), timestamp);
+        }
+    }
+
     /**
      * Called when the key dispatching to a window associated with the app window container
      * timed-out.
@@ -3361,6 +5626,780 @@
         }
     }
 
+    void postWindowRemoveStartingWindowCleanup(WindowState win) {
+        // TODO: Something smells about the code below...Is there a better way?
+        if (startingWindow == win) {
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Notify removed startingWindow %s", win);
+            removeStartingWindow();
+        } else if (mChildren.size() == 0) {
+            // If this is the last window and we had requested a starting transition window,
+            // well there is no point now.
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData");
+            mStartingData = null;
+            if (mHiddenSetFromTransferredStartingWindow) {
+                // We set the hidden state to false for the token from a transferred starting window.
+                // We now reset it back to true since the starting window was the last window in the
+                // token.
+                setHidden(true);
+            }
+        } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
+            // If this is the last window except for a starting transition window,
+            // we need to get rid of the starting transition.
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Last window, removing starting window %s", win);
+            removeStartingWindow();
+        }
+    }
+
+    void removeDeadWindows() {
+        for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
+            WindowState win = mChildren.get(winNdx);
+            if (win.mAppDied) {
+                ProtoLog.w(WM_DEBUG_ADD_REMOVE,
+                        "removeDeadWindows: %s", win);
+                // Set mDestroying, we don't want any animation or delayed removal here.
+                win.mDestroying = true;
+                // Also removes child windows.
+                win.removeIfPossible();
+            }
+        }
+    }
+
+    boolean hasWindowsAlive() {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            // No need to loop through child windows as the answer should be the same as that of the
+            // parent window.
+            if (!(mChildren.get(i)).mAppDied) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void setWillReplaceWindows(boolean animate) {
+        ProtoLog.d(WM_DEBUG_ADD_REMOVE,
+                "Marking app token %s with replacing windows.", this);
+
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            w.setWillReplaceWindow(animate);
+        }
+    }
+
+    void setWillReplaceChildWindows() {
+        ProtoLog.d(WM_DEBUG_ADD_REMOVE, "Marking app token %s"
+                + " with replacing child windows.", this);
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            w.setWillReplaceChildWindows();
+        }
+    }
+
+    void clearWillReplaceWindows() {
+        ProtoLog.d(WM_DEBUG_ADD_REMOVE,
+                "Resetting app token %s of replacing window marks.", this);
+
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            w.clearWillReplaceWindow();
+        }
+    }
+
+    void requestUpdateWallpaperIfNeeded() {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            w.requestUpdateWallpaperIfNeeded();
+        }
+    }
+
+    /**
+     * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
+     *         true.
+     */
+    WindowState getTopFullscreenWindow() {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = mChildren.get(i);
+            if (win != null && win.mAttrs.isFullscreen()) {
+                return win;
+            }
+        }
+        return null;
+    }
+
+    WindowState findMainWindow() {
+        return findMainWindow(true);
+    }
+
+    /**
+     * Finds the main window that either has type base application or application starting if
+     * requested.
+     *
+     * @param includeStartingApp Allow to search application-starting windows to also be returned.
+     * @return The main window of type base application or application starting if requested.
+     */
+    WindowState findMainWindow(boolean includeStartingApp) {
+        WindowState candidate = null;
+        for (int j = mChildren.size() - 1; j >= 0; --j) {
+            final WindowState win = mChildren.get(j);
+            final int type = win.mAttrs.type;
+            // No need to loop through child window as base application and starting types can't be
+            // child windows.
+            if (type == TYPE_BASE_APPLICATION
+                    || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
+                // In cases where there are multiple windows, we prefer the non-exiting window. This
+                // happens for example when replacing windows during an activity relaunch. When
+                // constructing the animation, we want the new window, not the exiting one.
+                if (win.mAnimatingExit) {
+                    candidate = win;
+                } else {
+                    return win;
+                }
+            }
+        }
+        return candidate;
+    }
+
+    SurfaceControl getAppAnimationLayer() {
+        return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
+                : needsZBoost() ? ANIMATION_LAYER_BOOSTED
+                        : ANIMATION_LAYER_STANDARD);
+    }
+
+    @Override
+    boolean needsZBoost() {
+        return mNeedsZBoost || super.needsZBoost();
+    }
+
+    @Override
+    public SurfaceControl getAnimationLeashParent() {
+        // For transitions in the pinned stack (menu activity) we just let them occur as a child
+        // of the pinned stack.
+        // All normal app transitions take place in an animation layer which is below the pinned
+        // stack but may be above the parent stacks of the given animating apps by default. When
+        // a new hierarchical animation is enabled, we just let them occur as a child of the parent
+        // stack, i.e. the hierarchy of the surfaces is unchanged.
+        if (inPinnedWindowingMode()) {
+            return getStack().getSurfaceControl();
+        } else if (WindowManagerService.sHierarchicalAnimations) {
+            return super.getAnimationLeashParent();
+        } else {
+            return getAppAnimationLayer();
+        }
+    }
+
+
+    @VisibleForTesting
+    boolean shouldAnimate(int transit) {
+        final boolean isSplitScreenPrimary =
+                getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+        final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
+
+        // Don't animate while the task runs recents animation but only if we are in the mode
+        // where we cancel with deferred screenshot, which means that the controller has
+        // transformed the task.
+        final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
+        if (controller != null && controller.isAnimatingTask(getTask())
+                && controller.shouldDeferCancelUntilNextTransition()) {
+            return false;
+        }
+
+        // We animate always if it's not split screen primary, and only some special cases in split
+        // screen primary because it causes issues with stack clipping when we run an un-minimize
+        // animation at the same time.
+        return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
+    }
+
+    /**
+     * Creates a layer to apply crop to an animation.
+     */
+    private SurfaceControl createAnimationBoundsLayer(Transaction t) {
+        ProtoLog.i(WM_DEBUG_APP_TRANSITIONS_ANIM, "Creating animation bounds layer");
+        final SurfaceControl.Builder builder = makeAnimationLeash()
+                .setParent(getAnimationLeashParent())
+                .setName(getSurfaceControl() + " - animation-bounds");
+        final SurfaceControl boundsLayer = builder.build();
+        t.show(boundsLayer);
+        return boundsLayer;
+    }
+
+    boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
+            boolean isVoiceInteraction) {
+
+        if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
+            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
+                    "applyAnimation: transition animation is disabled or skipped. "
+                            + "atoken=%s", this);
+            cancelAnimation();
+            return false;
+        }
+
+        // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
+        // to animate and it can cause strange artifacts when we unfreeze the display if some
+        // different animation is running.
+        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
+        if (okToAnimate()) {
+            final AnimationAdapter adapter;
+            AnimationAdapter thumbnailAdapter = null;
+
+            final int appStackClipMode =
+                    getDisplayContent().mAppTransition.getAppStackClipMode();
+
+            // Separate position and size for use in animators.
+            mTmpRect.set(getAnimationBounds(appStackClipMode));
+            mTmpPoint.set(mTmpRect.left, mTmpRect.top);
+            mTmpRect.offsetTo(0, 0);
+
+            final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
+                    && getDisplayContent().mChangingApps.contains(this);
+
+            // Delaying animation start isn't compatible with remote animations at all.
+            if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
+                    && !mSurfaceAnimator.isAnimationStartDelayed()) {
+                RemoteAnimationController.RemoteAnimationRecord adapters =
+                        getDisplayContent().mAppTransition.getRemoteAnimationController()
+                                .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
+                                        (isChanging ? mTransitStartRect : null));
+                adapter = adapters.mAdapter;
+                thumbnailAdapter = adapters.mThumbnailAdapter;
+            } else if (isChanging) {
+                final float durationScale = mWmService.getTransitionAnimationScaleLocked();
+                mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
+                adapter = new LocalAnimationAdapter(
+                        new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
+                                getDisplayContent().getDisplayInfo(), durationScale,
+                                true /* isAppAnimation */, false /* isThumbnail */),
+                        mWmService.mSurfaceAnimationRunner);
+                if (mThumbnail != null) {
+                    thumbnailAdapter = new LocalAnimationAdapter(
+                            new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
+                                    getDisplayContent().getDisplayInfo(), durationScale,
+                                    true /* isAppAnimation */, true /* isThumbnail */),
+                            mWmService.mSurfaceAnimationRunner);
+                }
+                mTransit = transit;
+                mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
+            } else {
+                mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
+
+                final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
+                if (a != null) {
+                    // Only apply corner radius to animation if we're not in multi window mode.
+                    // We don't want rounded corners when in pip or split screen.
+                    final float windowCornerRadius = !inMultiWindowMode()
+                            ? getDisplayContent().getWindowCornerRadius()
+                            : 0;
+                    adapter = new LocalAnimationAdapter(
+                            new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
+                                    getDisplayContent().mAppTransition.canSkipFirstFrame(),
+                                    appStackClipMode,
+                                    true /* isAppAnimation */,
+                                    windowCornerRadius),
+                            mWmService.mSurfaceAnimationRunner);
+                    if (a.getZAdjustment() == Animation.ZORDER_TOP) {
+                        mNeedsZBoost = true;
+                    }
+                    mTransit = transit;
+                    mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
+                } else {
+                    adapter = null;
+                }
+            }
+            if (adapter != null) {
+                startAnimation(getPendingTransaction(), adapter, !isVisible());
+                if (adapter.getShowWallpaper()) {
+                    mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+                }
+                if (thumbnailAdapter != null) {
+                    mThumbnail.startAnimation(
+                            getPendingTransaction(), thumbnailAdapter, !isVisible());
+                }
+            }
+        } else {
+            cancelAnimation();
+        }
+        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+
+        return isReallyAnimating();
+    }
+
+    private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
+            boolean isVoiceInteraction) {
+        final DisplayContent displayContent = getTask().getDisplayContent();
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final int width = displayInfo.appWidth;
+        final int height = displayInfo.appHeight;
+        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
+                "applyAnimation: atoken=%s", this);
+
+        // Determine the visible rect to calculate the thumbnail clip
+        final WindowState win = findMainWindow();
+        final Rect frame = new Rect(0, 0, width, height);
+        final Rect displayFrame = new Rect(0, 0,
+                displayInfo.logicalWidth, displayInfo.logicalHeight);
+        final Rect insets = new Rect();
+        final Rect stableInsets = new Rect();
+        Rect surfaceInsets = null;
+        final boolean freeform = win != null && win.inFreeformWindowingMode();
+        if (win != null) {
+            // Containing frame will usually cover the whole screen, including dialog windows.
+            // For freeform workspace windows it will not cover the whole screen and it also
+            // won't exactly match the final freeform window frame (e.g. when overlapping with
+            // the status bar). In that case we need to use the final frame.
+            if (freeform) {
+                frame.set(win.getFrameLw());
+            } else if (win.isLetterboxedAppWindow()) {
+                frame.set(getTask().getBounds());
+            } else if (win.isDockedResizing()) {
+                // If we are animating while docked resizing, then use the stack bounds as the
+                // animation target (which will be different than the task bounds)
+                frame.set(getTask().getParent().getBounds());
+            } else {
+                frame.set(win.getContainingFrame());
+            }
+            surfaceInsets = win.getAttrs().surfaceInsets;
+            // XXX(b/72757033): These are insets relative to the window frame, but we're really
+            // interested in the insets relative to the frame we chose in the if-blocks above.
+            win.getContentInsets(insets);
+            win.getStableInsets(stableInsets);
+        }
+
+        if (mLaunchTaskBehind) {
+            // Differentiate the two animations. This one which is briefly on the screen
+            // gets the !enter animation, and the other activity which remains on the
+            // screen gets the enter animation. Both appear in the mOpeningApps set.
+            enter = false;
+        }
+        ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
+                "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
+                        + "surfaceInsets=%s",
+                AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
+        final Configuration displayConfig = displayContent.getConfiguration();
+        final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
+                displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
+                surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
+        if (a != null) {
+            if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
+            final int containingWidth = frame.width();
+            final int containingHeight = frame.height();
+            a.initialize(containingWidth, containingHeight, width, height);
+            a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
+        }
+        return a;
+    }
+
+    @Override
+    public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
+        return mAnimatingActivityRegistry != null
+                && mAnimatingActivityRegistry.notifyAboutToFinish(
+                this, endDeferFinishCallback);
+    }
+
+    private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
+        if (mWmService.mDisableTransitionAnimation
+                || !isVisible()
+                || getDisplayContent().mAppTransition.isTransitionSet()
+                || getSurfaceControl() == null) {
+            return false;
+        }
+        // Only do an animation into and out-of freeform mode for now. Other mode
+        // transition animations are currently handled by system-ui.
+        return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
+    }
+
+    boolean isWaitingForTransitionStart() {
+        final DisplayContent dc = getDisplayContent();
+        // TODO: Test for null can be removed once unification is done.
+        if (dc == null) return false;
+        return dc.mAppTransition.isTransitionSet()
+                && (dc.mOpeningApps.contains(this)
+                || dc.mClosingApps.contains(this)
+                || dc.mChangingApps.contains(this));
+    }
+
+    /**
+     * Initializes a change transition. Because the app is visible already, there is a small period
+     * of time where the user can see the app content/window update before the transition starts.
+     * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
+     * "freezes" the location/crop until the transition starts.
+     * <p>
+     * Here's a walk-through of the process:
+     * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
+     * 2. Set the temporary leash's position/crop to the current state.
+     * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
+     * 4. Once the transition is ready, it will reparent the app to the animation leash.
+     * 5. Detach the interim-change-leash.
+     */
+    private void initializeChangeTransition(Rect startBounds) {
+        mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
+                false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
+        mDisplayContent.mChangingApps.add(this);
+        mTransitStartRect.set(startBounds);
+
+        final SurfaceControl.Builder builder = makeAnimationLeash()
+                .setParent(getAnimationLeashParent())
+                .setName(getSurfaceControl() + " - interim-change-leash");
+        mTransitChangeLeash = builder.build();
+        Transaction t = getPendingTransaction();
+        t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
+        t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
+        t.show(mTransitChangeLeash);
+        t.reparent(getSurfaceControl(), mTransitChangeLeash);
+        onAnimationLeashCreated(t, mTransitChangeLeash);
+
+        // Skip creating snapshot if this transition is controlled by a remote animator which
+        // doesn't need it.
+        ArraySet<Integer> activityTypes = new ArraySet<>();
+        activityTypes.add(getActivityType());
+        RemoteAnimationAdapter adapter =
+                mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
+                        this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
+        if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
+            return;
+        }
+
+        Task task = getTask();
+        if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
+            SurfaceControl.ScreenshotGraphicBuffer snapshot =
+                    mWmService.mTaskSnapshotController.createTaskSnapshot(
+                            task, 1 /* scaleFraction */);
+            if (snapshot != null) {
+                mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, t, this,
+                        snapshot.getGraphicBuffer(), true /* relative */);
+            }
+        }
+    }
+
+    @Override
+    public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
+        // The leash is parented to the animation layer. We need to preserve the z-order by using
+        // the prefix order index, but we boost if necessary.
+        int layer = 0;
+        if (!inPinnedWindowingMode()) {
+            layer = getPrefixOrderIndex();
+        } else {
+            // Pinned stacks have animations take place within themselves rather than an animation
+            // layer so we need to preserve the order relative to the stack (e.g. the order of our
+            // task/parent).
+            layer = getParent().getPrefixOrderIndex();
+        }
+
+        if (mNeedsZBoost) {
+            layer += Z_BOOST_BASE;
+        }
+        if (!mNeedsAnimationBoundsLayer) {
+            t.setLayer(leash, layer);
+        }
+
+        final DisplayContent dc = getDisplayContent();
+        dc.assignStackOrdering();
+
+        if (leash == mTransitChangeLeash) {
+            // This is a temporary state so skip any animation notifications
+            return;
+        } else if (mTransitChangeLeash != null) {
+            // unparent mTransitChangeLeash for clean-up
+            clearChangeLeash(t, false /* cancel */);
+        }
+
+        if (mAnimatingActivityRegistry != null) {
+            mAnimatingActivityRegistry.notifyStarting(this);
+        }
+
+        // If the animation needs to be cropped then an animation bounds layer is created as a child
+        // of the pinned stack or animation layer. The leash is then reparented to this new layer.
+        if (mNeedsAnimationBoundsLayer) {
+            mTmpRect.setEmpty();
+            final Task task = getTask();
+            if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
+                    getTransit(), task)) {
+                task.getBounds(mTmpRect);
+            } else {
+                final TaskStack stack = getStack();
+                if (stack == null) {
+                    return;
+                }
+                // Set clip rect to stack bounds.
+                stack.getBounds(mTmpRect);
+            }
+            mAnimationBoundsLayer = createAnimationBoundsLayer(t);
+
+            // Crop to stack bounds.
+            t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
+            t.setLayer(mAnimationBoundsLayer, layer);
+
+            // Reparent leash to animation bounds layer.
+            t.reparent(leash, mAnimationBoundsLayer);
+        }
+    }
+
+    @Override
+    void prepareSurfaces() {
+        // isSelfAnimating also returns true when we are about to start a transition, so we need
+        // to check super here.
+        final boolean reallyAnimating = super.isSelfAnimating();
+        final boolean show = !isHidden() || reallyAnimating;
+
+        if (mSurfaceControl != null) {
+            if (show && !mLastSurfaceShowing) {
+                getPendingTransaction().show(mSurfaceControl);
+            } else if (!show && mLastSurfaceShowing) {
+                getPendingTransaction().hide(mSurfaceControl);
+            }
+        }
+        if (mThumbnail != null) {
+            mThumbnail.setShowing(getPendingTransaction(), show);
+        }
+        mLastSurfaceShowing = show;
+        super.prepareSurfaces();
+    }
+
+    /**
+     * @return Whether our {@link #getSurfaceControl} is currently showing.
+     */
+    boolean isSurfaceShowing() {
+        return mLastSurfaceShowing;
+    }
+
+    boolean isInChangeTransition() {
+        return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
+    }
+
+    void attachThumbnailAnimation() {
+        if (!isReallyAnimating()) {
+            return;
+        }
+        final int taskId = getTask().mTaskId;
+        final GraphicBuffer thumbnailHeader =
+                getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
+        if (thumbnailHeader == null) {
+            ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %d", taskId);
+            return;
+        }
+        clearThumbnail();
+        mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, getPendingTransaction(),
+                this, thumbnailHeader);
+        mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
+    }
+
+    /**
+     * Attaches a surface with a thumbnail for the
+     * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
+     */
+    void attachCrossProfileAppsThumbnailAnimation() {
+        if (!isReallyAnimating()) {
+            return;
+        }
+        clearThumbnail();
+
+        final WindowState win = findMainWindow();
+        if (win == null) {
+            return;
+        }
+        final Rect frame = win.getFrameLw();
+        final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
+                ? R.drawable.ic_account_circle
+                : R.drawable.ic_corp_badge;
+        final GraphicBuffer thumbnail =
+                getDisplayContent().mAppTransition
+                        .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
+        if (thumbnail == null) {
+            return;
+        }
+        mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory,
+                getPendingTransaction(), this, thumbnail);
+        final Animation animation =
+                getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
+                        win.getFrameLw());
+        mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
+                frame.top));
+    }
+
+    private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
+        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+
+        // If this is a multi-window scenario, we use the windows frame as
+        // destination of the thumbnail header animation. If this is a full screen
+        // window scenario, we use the whole display as the target.
+        WindowState win = findMainWindow();
+        Rect appRect = win != null ? win.getContentFrameLw() :
+                new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
+        final Rect insets = win != null ? win.getContentInsets() : null;
+        final Configuration displayConfig = mDisplayContent.getConfiguration();
+        return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
+                appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
+                displayConfig.orientation);
+    }
+
+    @Override
+    boolean isAppAnimating() {
+        return isSelfAnimating();
+    }
+
+    @Override
+    boolean isSelfAnimating() {
+        // If we are about to start a transition, we also need to be considered animating.
+        return isWaitingForTransitionStart() || isReallyAnimating();
+    }
+
+    @Override
+    public void onAnimationLeashLost(Transaction t) {
+        super.onAnimationLeashLost(t);
+        if (mAnimationBoundsLayer != null) {
+            t.remove(mAnimationBoundsLayer);
+            mAnimationBoundsLayer = null;
+        }
+
+        if (mAnimatingActivityRegistry != null) {
+            mAnimatingActivityRegistry.notifyFinished(this);
+        }
+    }
+
+    @Override
+    protected void onAnimationFinished() {
+        super.onAnimationFinished();
+
+        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
+        mTransit = TRANSIT_UNSET;
+        mTransitFlags = 0;
+        mNeedsZBoost = false;
+        mNeedsAnimationBoundsLayer = false;
+
+        setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
+                "AppWindowToken");
+
+        clearThumbnail();
+        setClientHidden(isHidden() && hiddenRequested);
+
+        getDisplayContent().computeImeTargetIfNeeded(this);
+
+        if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
+                + ": reportedVisible=" + reportedVisible
+                + " okToDisplay=" + okToDisplay()
+                + " okToAnimate=" + okToAnimate()
+                + " startingDisplayed=" + startingDisplayed);
+
+        // clean up thumbnail window
+        if (mThumbnail != null) {
+            mThumbnail.destroy();
+            mThumbnail = null;
+        }
+
+        // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
+        // traverse the copy.
+        final ArrayList<WindowState> children = new ArrayList<>(mChildren);
+        children.forEach(WindowState::onExitAnimationDone);
+
+        getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
+        scheduleAnimation();
+
+        if (mAtmService.mRootActivityContainer.allResumedActivitiesIdle()
+                || mAtmService.mStackSupervisor.isStoppingNoHistoryActivity()) {
+            // If all activities are already idle or there is an activity that must be
+            // stopped immediately after visible, then we now need to make sure we perform
+            // the full stop of this activity. This is because we won't do that while they are still
+            // waiting for the animation to finish.
+            if (mAtmService.mStackSupervisor.mStoppingActivities.contains(this)) {
+                mAtmService.mStackSupervisor.scheduleIdleLocked();
+            }
+        } else {
+            // Instead of doing the full stop routine here, let's just hide any activities
+            // we now can, and let them stop when the normal idle happens.
+            mAtmService.mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
+                    false /* remove */, true /* processPausingActivities */);
+        }
+        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+    }
+
+    /**
+     * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
+     *                            to another leash.
+     */
+    private void clearChangeLeash(Transaction t, boolean cancel) {
+        if (mTransitChangeLeash == null) {
+            return;
+        }
+        if (cancel) {
+            clearThumbnail();
+            SurfaceControl sc = getSurfaceControl();
+            SurfaceControl parentSc = getParentSurfaceControl();
+            // Don't reparent if surface is getting destroyed
+            if (parentSc != null && sc != null) {
+                t.reparent(sc, getParentSurfaceControl());
+            }
+        }
+        t.hide(mTransitChangeLeash);
+        t.remove(mTransitChangeLeash);
+        mTransitChangeLeash = null;
+        if (cancel) {
+            onAnimationLeashLost(t);
+        }
+    }
+
+    void clearAnimatingFlags() {
+        boolean wallpaperMightChange = false;
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = mChildren.get(i);
+            wallpaperMightChange |= win.clearAnimatingFlags();
+        }
+        if (wallpaperMightChange) {
+            requestUpdateWallpaperIfNeeded();
+        }
+    }
+
+    /**
+     * @return True if and only if we are actually running an animation. Note that
+     *         {@link #isSelfAnimating} also returns true if we are waiting for an animation to
+     *         start.
+     */
+    private boolean isReallyAnimating() {
+        return super.isSelfAnimating();
+    }
+
+    @Override
+    void cancelAnimation() {
+        cancelAnimationOnly();
+        clearThumbnail();
+        clearChangeLeash(getPendingTransaction(), true /* cancel */);
+    }
+
+    /**
+     * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
+     * or interim leashes.
+     * <p>
+     * Used when canceling in preparation for starting a new animation.
+     */
+    void cancelAnimationOnly() {
+        super.cancelAnimation();
+    }
+
+    @VisibleForTesting
+    AppWindowThumbnail getThumbnail() {
+        return mThumbnail;
+    }
+
+    private void clearThumbnail() {
+        if (mThumbnail == null) {
+            return;
+        }
+        mThumbnail.destroy();
+        mThumbnail = null;
+    }
+
+    public int getTransit() {
+        return mTransit;
+    }
+
+    int getTransitFlags() {
+        return mTransitFlags;
+    }
+
+    void registerRemoteAnimations(RemoteAnimationDefinition definition) {
+        mRemoteAnimationDefinition = definition;
+    }
+
+    RemoteAnimationDefinition getRemoteAnimationDefinition() {
+        return mRemoteAnimationDefinition;
+    }
+
     void setRequestedOrientation(int requestedOrientation) {
         setOrientation(requestedOrientation, mayFreezeScreenLocked());
         mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
@@ -3380,6 +6419,49 @@
         }
     }
 
+    void reportDescendantOrientationChangeIfNeeded() {
+        // Orientation request is exposed only when we're visible. Therefore visibility change
+        // will change requested orientation. Notify upward the hierarchy ladder to adjust
+        // configuration. This is important to cases where activities with incompatible
+        // orientations launch, or user goes back from an activity of bi-orientation to an
+        // activity with specified orientation.
+        if (getRequestedOrientation() == SCREEN_ORIENTATION_UNSET) {
+            return;
+        }
+
+        final IBinder freezeToken = mayFreezeScreenLocked() ? appToken : null;
+        onDescendantOrientationChanged(freezeToken, this);
+    }
+
+    /**
+     * We override because this class doesn't want its children affecting its reported orientation
+     * in anyway.
+     */
+    @Override
+    int getOrientation(int candidate) {
+        if (candidate == SCREEN_ORIENTATION_BEHIND) {
+            // Allow app to specify orientation regardless of its visibility state if the current
+            // candidate want us to use orientation behind. I.e. the visible app on-top of this one
+            // wants us to use the orientation of the app behind it.
+            return mOrientation;
+        }
+
+        // The {@link ActivityRecord} should only specify an orientation when it is not closing or
+        // going to the bottom. Allowing closing {@link ActivityRecord} to participate can lead to
+        // an Activity in another task being started in the wrong orientation during the transition.
+        if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
+                && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
+            return mOrientation;
+        }
+
+        return SCREEN_ORIENTATION_UNSET;
+    }
+
+    /** Returns the app's preferred orientation regardless of its currently visibility state. */
+    int getRequestedOrientation() {
+        return mOrientation;
+    }
+
     /**
      * Set the last reported global configuration to the client. Should be called whenever a new
      * global configuration is sent to the client for this activity.
@@ -3479,6 +6561,10 @@
                 && !mAtmService.mForceResizableActivities;
     }
 
+    boolean hasSizeCompatBounds() {
+        return mSizeCompatBounds != null;
+    }
+
     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
     private void updateOverrideConfiguration() {
         final Configuration overrideConfig = mTmpConfig;
@@ -3535,6 +6621,22 @@
     }
 
     @Override
+    public boolean matchParentBounds() {
+        if (super.matchParentBounds()) {
+            return true;
+        }
+        // An activity in size compatibility mode may have override bounds which equals to its
+        // parent bounds, so the exact bounds should also be checked.
+        final WindowContainer parent = getParent();
+        return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
+    }
+
+    @Override
+    float getSizeCompatScale() {
+        return hasSizeCompatBounds() ? mSizeCompatScale : super.getSizeCompatScale();
+    }
+
+    @Override
     void resolveOverrideConfiguration(Configuration newParentConfiguration) {
         if (mCompatDisplayInsets != null) {
             resolveSizeCompatModeConfiguration(newParentConfiguration);
@@ -3542,7 +6644,7 @@
             super.resolveOverrideConfiguration(newParentConfiguration);
             // If the activity has override bounds, the relative configuration (e.g. screen size,
             // layout) needs to be resolved according to the bounds.
-            if (!matchParentBounds()) {
+            if (task != null && !matchParentBounds()) {
                 task.computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
                         newParentConfiguration);
             }
@@ -3630,7 +6732,7 @@
                 mCompatDisplayInsets);
 
         // The horizontal inset included in width is not needed if the activity cannot fill the
-        // parent, because the offset will be applied by {@link AppWindowToken#mSizeCompatBounds}.
+        // parent, because the offset will be applied by {@link ActivityRecord#mSizeCompatBounds}.
         final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
         final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
         if (resolvedBounds.width() < parentAppBounds.width()) {
@@ -3644,9 +6746,100 @@
     }
 
     @Override
+    public Rect getBounds() {
+        if (mSizeCompatBounds != null) {
+            return mSizeCompatBounds;
+        }
+        return super.getBounds();
+    }
+
+    @Override
+    Rect getDisplayedBounds() {
+        final Task task = getTask();
+        if (task != null) {
+            final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
+            if (!overrideDisplayedBounds.isEmpty()) {
+                return overrideDisplayedBounds;
+            }
+        }
+        return getBounds();
+    }
+
+    @VisibleForTesting
+    Rect getAnimationBounds(int appStackClipMode) {
+        if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
+            // Using the stack bounds here effectively applies the clipping before animation.
+            return getStack().getBounds();
+        }
+        // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
+        // included in the animation.
+        return getTask() != null ? getTask().getBounds() : getBounds();
+    }
+
+    /**
+     * Calculates the scale and offset to horizontal center the size compatibility bounds into the
+     * region which is available to application.
+     */
+    private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
+        final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
+        final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
+        final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
+        final Rect appBounds = getWindowConfiguration().getAppBounds();
+        final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
+        final float contentW = contentBounds.width();
+        final float contentH = contentBounds.height();
+        final float viewportW = viewportBounds.width();
+        final float viewportH = viewportBounds.height();
+        // Only allow to scale down.
+        mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
+                ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
+        final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
+                + viewportBounds.left;
+
+        if (mSizeCompatBounds == null) {
+            mSizeCompatBounds = new Rect();
+        }
+        mSizeCompatBounds.set(contentBounds);
+        mSizeCompatBounds.offsetTo(0, 0);
+        mSizeCompatBounds.scale(mSizeCompatScale);
+        // Ensure to align the top with the parent.
+        mSizeCompatBounds.top = parentBounds.top;
+        // The decor inset is included in height.
+        mSizeCompatBounds.bottom += viewportBounds.top;
+        mSizeCompatBounds.left += offsetX;
+        mSizeCompatBounds.right += offsetX;
+    }
+
+    @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
+        final int prevWinMode = getWindowingMode();
+        mTmpPrevBounds.set(getBounds());
         super.onConfigurationChanged(newParentConfig);
 
+        final Task task = getTask();
+        final Rect overrideBounds = getResolvedOverrideBounds();
+        if (task != null && !overrideBounds.isEmpty()
+                // If the changes come from change-listener, the incoming parent configuration is
+                // still the old one. Make sure their orientations are the same to reduce computing
+                // the compatibility bounds for the intermediate state.
+                && (task.mTaskRecord == null || task.mTaskRecord
+                .getConfiguration().orientation == newParentConfig.orientation)) {
+            final Rect taskBounds = task.getBounds();
+            // Since we only center the activity horizontally, if only the fixed height is smaller
+            // than its container, the override bounds don't need to take effect.
+            if ((overrideBounds.width() != taskBounds.width()
+                    || overrideBounds.height() > taskBounds.height())) {
+                calculateCompatBoundsTransformation(newParentConfig);
+                updateSurfacePosition();
+            } else if (mSizeCompatBounds != null) {
+                mSizeCompatBounds = null;
+                mSizeCompatScale = 1f;
+                updateSurfacePosition();
+            }
+        }
+
+        adjustPinnedStackAndInitChangeTransitionIfNeeded(prevWinMode, getWindowingMode());
+
         // Configuration's equality doesn't consider seq so if only seq number changes in resolved
         // override configuration. Therefore ConfigurationContainer doesn't change merged override
         // configuration, but it's used to push configuration changes so explicitly update that.
@@ -3679,6 +6872,37 @@
         }
     }
 
+    private void adjustPinnedStackAndInitChangeTransitionIfNeeded(int prevWinMode, int winMode) {
+        if (prevWinMode == winMode || mDisplayContent == null) {
+            return;
+        }
+
+        if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
+                && !isHidden()) {
+            // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
+            // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
+            final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
+            if (pinnedStack != null) {
+                final Rect stackBounds;
+                if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
+                    // We are animating the bounds, use the pre-animation bounds to save the snap
+                    // fraction
+                    stackBounds = pinnedStack.mPreAnimationBounds;
+                } else {
+                    // We skip the animation if the fullscreen configuration is not compatible, so
+                    // use the current bounds to calculate the saved snap fraction instead
+                    // (see PinnedActivityStack.skipResizeAnimation())
+                    stackBounds = mTmpRect;
+                    pinnedStack.getBounds(stackBounds);
+                }
+                mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(
+                        mActivityComponent, stackBounds);
+            }
+        } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
+            initializeChangeTransition(mTmpPrevBounds);
+        }
+    }
+
     /** Returns true if the configuration is compatible with this activity. */
     boolean isConfigurationCompatible(Configuration config) {
         final int orientation = getRequestedOrientation();
@@ -4198,12 +7422,19 @@
             return true;
         }
 
-        // Restrict task snapshot starting window to launcher start, or there is no intent at all
-        // (eg. task being brought to front). If the intent is something else, likely the app is
-        // going to show some specific page or view, instead of what's left last time.
+        // Restrict task snapshot starting window to launcher start, or is same as the last
+        // delivered intent, or there is no intent at all (eg. task being brought to front). If
+        // the intent is something else, likely the app is going to show some specific page or
+        // view, instead of what's left last time.
         for (int i = newIntents.size() - 1; i >= 0; i--) {
             final Intent intent = newIntents.get(i);
-            if (intent != null && !ActivityRecord.isMainIntent(intent)) {
+            if (intent == null || ActivityRecord.isMainIntent(intent)) {
+                continue;
+            }
+
+            final boolean sameIntent = mLastNewIntent != null ? mLastNewIntent.filterEquals(intent)
+                    : this.intent.filterEquals(intent);
+            if (!sameIntent || intent.getExtras() != null) {
                 return false;
             }
         }
@@ -4337,14 +7568,13 @@
         return info.applicationInfo.uid;
     }
 
-    @Override
     int getPid() {
         return app != null ? app.getPid() : 0;
     }
 
     /**
      * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag
-     * {@link AppWindowToken#getTurnScreenOnFlag} is set and checks whether the ActivityRecord
+     * {@link ActivityRecord#getTurnScreenOnFlag} is set and checks whether the ActivityRecord
      * should be visible depending on Keyguard state
      *
      * @return true if the screen can be turned on, false otherwise.
@@ -4358,6 +7588,14 @@
                 stack.checkKeyguardVisibility(this, true /* shouldBeVisible */, true /* isTop */);
     }
 
+    void setTurnScreenOn(boolean turnScreenOn) {
+        mTurnScreenOn = turnScreenOn;
+    }
+
+    boolean getTurnScreenOnFlag() {
+        return mTurnScreenOn;
+    }
+
     /**
      * Check if this activity is able to resume. For pre-Q apps, only the topmost activities of each
      * process are allowed to be resumed.
@@ -4424,7 +7662,7 @@
      * {@code ActivityRecordProto} is the outer-most proto data.
      */
     void writeToProto(ProtoOutputStream proto) {
-        super.writeToProto(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL);
+        writeToProto(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL);
         writeIdentifierToProto(proto, IDENTIFIER);
         proto.write(STATE, mState.toString());
         proto.write(VISIBLE, visible);
@@ -4442,6 +7680,65 @@
     }
 
     /**
+     * Copied from old AppWindowToken.
+     */
+    @Override
+    public void writeToProto(ProtoOutputStream proto, long fieldId,
+            @WindowTraceLogLevel int logLevel) {
+        // Critical log level logs only visible elements to mitigate performance overheard
+        if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
+            return;
+        }
+
+        final long token = proto.start(fieldId);
+        writeNameToProto(proto, NAME);
+        super.writeToProto(proto, WINDOW_TOKEN, logLevel);
+        proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
+        proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
+        proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
+        if (mThumbnail != null){
+            mThumbnail.writeToProto(proto, THUMBNAIL);
+        }
+        proto.write(FILLS_PARENT, mOccludesParent);
+        proto.write(APP_STOPPED, mAppStopped);
+        proto.write(HIDDEN_REQUESTED, hiddenRequested);
+        proto.write(CLIENT_HIDDEN, mClientHidden);
+        proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
+        proto.write(REPORTED_DRAWN, reportedDrawn);
+        proto.write(REPORTED_VISIBLE, reportedVisible);
+        proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
+        proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
+        proto.write(ALL_DRAWN, allDrawn);
+        proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
+        proto.write(REMOVED, removed);
+        if (startingWindow != null) {
+            startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
+        }
+        proto.write(STARTING_DISPLAYED, startingDisplayed);
+        proto.write(STARTING_MOVED, startingMoved);
+        proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
+                mHiddenSetFromTransferredStartingWindow);
+        for (Rect bounds : mFrozenBounds) {
+            bounds.writeToProto(proto, FROZEN_BOUNDS);
+        }
+        proto.end(token);
+    }
+
+    void writeNameToProto(ProtoOutputStream proto, long fieldId) {
+        if (appToken != null) {
+            proto.write(fieldId, appToken.getName());
+        }
+    }
+
+    void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+        proto.write(HASH_CODE, System.identityHashCode(this));
+        proto.write(USER_ID, mUserId);
+        proto.write(TITLE, intent.getComponent().flattenToShortString());
+        proto.end(token);
+    }
+
+    /**
      * The precomputed insets of the display in each rotation. This is used to make the size
      * compatibility mode activity compute the configuration without relying on its current display.
      */
@@ -4494,4 +7791,14 @@
                     isLandscape ? shortSide : longSide);
         }
     }
+
+    private static class AppSaturationInfo {
+        float[] mMatrix = new float[9];
+        float[] mTranslation = new float[3];
+
+        void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
+            System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
+            System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 5959254..41c1e4e 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -33,7 +33,7 @@
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
 import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
 import static android.view.Display.INVALID_DISPLAY;
@@ -488,7 +488,7 @@
     int numActivities() {
         int count = 0;
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            count += mTaskHistory.get(taskNdx).mActivities.size();
+            count += mTaskHistory.get(taskNdx).getChildCount();
         }
         return count;
     }
@@ -1077,9 +1077,8 @@
     ActivityRecord topRunningNonOverlayTaskActivity() {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
-            final ArrayList<ActivityRecord> activities = task.mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 if (!r.finishing && !r.mTaskOverlay) {
                     return r;
                 }
@@ -1091,9 +1090,8 @@
     ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
-            final ArrayList<ActivityRecord> activities = task.mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                ActivityRecord r = activities.get(activityNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 if (!r.finishing && !r.delayedResume && r != notTop && r.okToShowLocked()) {
                     return r;
                 }
@@ -1117,9 +1115,8 @@
             if (task.mTaskId == taskId) {
                 continue;
             }
-            ArrayList<ActivityRecord> activities = task.mActivities;
-            for (int i = activities.size() - 1; i >= 0; --i) {
-                final ActivityRecord r = activities.get(i);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 // Note: the taskId check depends on real taskId fields being non-zero
                 if (!r.finishing && (token != r.appToken) && r.okToShowLocked()) {
                     return r;
@@ -1431,10 +1428,8 @@
 
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
-            final ArrayList<ActivityRecord> activities = task.mActivities;
-
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                ActivityRecord r = activities.get(activityNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 if (!r.okToShowLocked()) {
                     continue;
                 }
@@ -1500,9 +1495,10 @@
     void awakeFromSleepingLocked() {
         // Ensure activities are no longer sleeping.
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                activities.get(activityNdx).setSleeping(false);
+            final TaskRecord task = mTaskHistory.get(taskNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
+                r.setSleeping(false);
             }
         }
         if (mPausingActivity != null) {
@@ -1516,9 +1512,9 @@
         final int userId = UserHandle.getUserId(aInfo.uid);
 
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            final List<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord ar = activities.get(activityNdx);
+            final TaskRecord task = mTaskHistory.get(taskNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord ar = task.getChildAt(activityNdx);
 
                 if ((userId == ar.mUserId) && packageName.equals(ar.packageName)) {
                     ar.updateApplicationInfo(aInfo);
@@ -1594,9 +1590,9 @@
         // Make sure any paused or stopped but visible activities are now sleeping.
         // This ensures that the activity's onStop() is called.
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
+            final TaskRecord task = mTaskHistory.get(taskNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 if (r.isState(STARTED, STOPPING, STOPPED, PAUSED, PAUSING)) {
                     r.setSleeping(true);
                 }
@@ -1880,9 +1876,8 @@
         }
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
-            final ArrayList<ActivityRecord> activities = task.mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
 
                 if (r.finishing) {
                     // We don't factor in finishing activities when determining translucency since
@@ -2113,9 +2108,8 @@
                     && top != null && !top.mLaunchTaskBehind;
             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
                 final TaskRecord task = mTaskHistory.get(taskNdx);
-                final ArrayList<ActivityRecord> activities = task.mActivities;
-                for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                    final ActivityRecord r = activities.get(activityNdx);
+                for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                    final ActivityRecord r = task.getChildAt(activityNdx);
                     final boolean isTop = r == top;
                     if (aboveTop && !isTop) {
                         continue;
@@ -2363,9 +2357,8 @@
     void clearOtherAppTimeTrackers(AppTimeTracker except) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
-            final ArrayList<ActivityRecord> activities = task.mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 if ( r.appTimeTracker != except) {
                     r.appTimeTracker = null;
                 }
@@ -2423,9 +2416,9 @@
         }
 
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
+            final TaskRecord task = mTaskHistory.get(taskNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 if (aboveTop) {
                     if (r == topActivity) {
                         aboveTop = false;
@@ -3210,14 +3203,13 @@
 
         // We only do this for activities that are not the root of the task (since if we finish
         // the root, we may no longer have the task!).
-        final ArrayList<ActivityRecord> activities = task.mActivities;
-        final int numActivities = activities.size();
+        final int numActivities = task.getChildCount();
         int lastActivityNdx = task.findRootIndex(true /* effectiveRoot */);
         if (lastActivityNdx == -1) {
             lastActivityNdx = 0;
         }
         for (int i = numActivities - 1; i > lastActivityNdx; --i) {
-            ActivityRecord target = activities.get(i);
+            ActivityRecord target = task.getChildAt(i);
             // TODO: Why is this needed? Looks like we're breaking the loop before we reach the root
             if (target.isRootOfTask()) break;
 
@@ -3257,7 +3249,7 @@
                 final TaskRecord targetTask;
                 final ActivityRecord bottom =
                         !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
-                                mTaskHistory.get(0).mActivities.get(0) : null;
+                                mTaskHistory.get(0).getChildAt(0) : null;
                 if (bottom != null && target.taskAffinity.equals(bottom.getTaskRecord().affinity)) {
                     // If the activity currently at the bottom has the
                     // same task affinity as the one we are moving,
@@ -3279,7 +3271,7 @@
                 boolean noOptions = canMoveOptions;
                 final int start = replyChainEnd < 0 ? i : replyChainEnd;
                 for (int srcPos = start; srcPos >= i; --srcPos) {
-                    final ActivityRecord p = activities.get(srcPos);
+                    final ActivityRecord p = task.getChildAt(srcPos);
                     if (p.finishing) {
                         continue;
                     }
@@ -3312,7 +3304,7 @@
                     // In this case, we want to finish this activity
                     // and everything above it, so be sneaky and pretend
                     // like these are all in the reply chain.
-                    end = activities.size() - 1;
+                    end = task.getChildCount() - 1;
                 } else if (replyChainEnd < 0) {
                     end = i;
                 } else {
@@ -3320,7 +3312,7 @@
                 }
                 boolean noOptions = canMoveOptions;
                 for (int srcPos = i; srcPos <= end; srcPos++) {
-                    ActivityRecord p = activities.get(srcPos);
+                    ActivityRecord p = task.getChildAt(srcPos);
                     if (p.finishing) {
                         continue;
                     }
@@ -3389,8 +3381,7 @@
         int replyChainEnd = -1;
         final String taskAffinity = task.affinity;
 
-        final ArrayList<ActivityRecord> activities = affinityTask.mActivities;
-        final int numActivities = activities.size();
+        final int numActivities = task.getChildCount();
 
         // Do not operate on or below the effective root Activity.
         int lastActivityNdx = affinityTask.findRootIndex(true /* effectiveRoot */);
@@ -3398,7 +3389,7 @@
             lastActivityNdx = 0;
         }
         for (int i = numActivities - 1; i > lastActivityNdx; --i) {
-            ActivityRecord target = activities.get(i);
+            ActivityRecord target = task.getChildAt(i);
             // TODO: Why is this needed? Looks like we're breaking the loop before we reach the root
             if (target.isRootOfTask()) break;
 
@@ -3435,7 +3426,7 @@
                     if (DEBUG_TASKS) Slog.v(TAG_TASKS,
                             "Finishing task at index " + start + " to " + i);
                     for (int srcPos = start; srcPos >= i; --srcPos) {
-                        final ActivityRecord p = activities.get(srcPos);
+                        final ActivityRecord p = task.getChildAt(srcPos);
                         if (p.finishing) {
                             continue;
                         }
@@ -3443,7 +3434,7 @@
                     }
                 } else {
                     if (taskInsertionPoint < 0) {
-                        taskInsertionPoint = task.mActivities.size();
+                        taskInsertionPoint = task.getChildCount();
 
                     }
 
@@ -3452,7 +3443,7 @@
                             "Reparenting from task=" + affinityTask + ":" + start + "-" + i
                             + " to task=" + task + ":" + taskInsertionPoint);
                     for (int srcPos = start; srcPos >= i; --srcPos) {
-                        final ActivityRecord p = activities.get(srcPos);
+                        final ActivityRecord p = task.getChildAt(srcPos);
                         p.reparent(task, taskInsertionPoint, "resetAffinityTaskIfNeededLocked");
 
                         if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
@@ -3589,9 +3580,9 @@
     /** Finish all activities that were started for result from the specified activity. */
     final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                ActivityRecord r = activities.get(activityNdx);
+            final TaskRecord task = mTaskHistory.get(taskNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 if (r.resultTo == self && r.requestCode == requestCode) {
                     if ((r.resultWho == null && resultWho == null) ||
                         (r.resultWho != null && r.resultWho.equals(resultWho))) {
@@ -3637,11 +3628,11 @@
                 if (taskNdx < 0) {
                     break;
                 }
-                activityNdx = mTaskHistory.get(taskNdx).mActivities.size() - 1;
+                activityNdx = mTaskHistory.get(taskNdx).getChildCount() - 1;
             } while (activityNdx < 0);
         }
         if (activityNdx >= 0) {
-            r = mTaskHistory.get(taskNdx).mActivities.get(activityNdx);
+            r = mTaskHistory.get(taskNdx).getChildAt(activityNdx);
             if (r.isState(STARTED, RESUMED, PAUSING, PAUSED)) {
                 if (!r.isActivityTypeHome() || mService.mHomeProcess != r.app) {
                     Slog.w(TAG, "  Force finishing activity "
@@ -3659,8 +3650,8 @@
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             TaskRecord tr = mTaskHistory.get(taskNdx);
             if (tr.voiceSession != null && tr.voiceSession.asBinder() == sessionBinder) {
-                for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
-                    ActivityRecord r = tr.mActivities.get(activityNdx);
+                for (int activityNdx = tr.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                    ActivityRecord r = tr.getChildAt(activityNdx);
                     if (!r.finishing) {
                         r.finishIfPossible("finish-voice", false /* oomAdj */);
                         didOne = true;
@@ -3668,8 +3659,8 @@
                 }
             } else {
                 // Check if any of the activities are using voice
-                for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
-                    ActivityRecord r = tr.mActivities.get(activityNdx);
+                for (int activityNdx = tr.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                    ActivityRecord r = tr.getChildAt(activityNdx);
                     if (r.voiceSession != null && r.voiceSession.asBinder() == sessionBinder) {
                         // Inform of cancellation
                         r.clearVoiceSessionLocked();
@@ -3695,9 +3686,9 @@
     void finishAllActivitiesImmediately() {
         boolean noActivitiesInStack = true;
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
+            final TaskRecord task = mTaskHistory.get(taskNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 noActivitiesInStack = false;
                 Slog.d(TAG, "finishAllActivitiesImmediatelyLocked: finishing " + r);
                 r.destroyIfPossible("finishAllActivitiesImmediatelyLocked");
@@ -3765,12 +3756,12 @@
             return false;
         }
         int finishTo = start - 1;
-        ActivityRecord parent = finishTo < 0 ? null : activities.get(finishTo);
+        ActivityRecord parent = finishTo < 0 ? null : task.getChildAt(finishTo);
         boolean foundParentInTask = false;
         final ComponentName dest = destIntent.getComponent();
         if (start > 0 && dest != null) {
             for (int i = finishTo; i >= 0; i--) {
-                ActivityRecord r = activities.get(i);
+                ActivityRecord r = task.getChildAt(i);
                 if (r.info.packageName.equals(dest.getPackageName()) &&
                         r.info.name.equals(dest.getClassName())) {
                     finishTo = i;
@@ -3931,9 +3922,9 @@
         boolean lastIsOpaque = false;
         boolean activityRemoved = false;
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
+            final TaskRecord task = mTaskHistory.get(taskNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 if (r.finishing) {
                     continue;
                 }
@@ -3978,15 +3969,14 @@
             }
             if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Looking for activities to release in " + task);
             int curNum = 0;
-            final ArrayList<ActivityRecord> activities = task.mActivities;
-            for (int actNdx = 0; actNdx < activities.size(); actNdx++) {
-                final ActivityRecord activity = activities.get(actNdx);
+            for (int actNdx = 0; actNdx < task.getChildCount(); actNdx++) {
+                final ActivityRecord activity = task.getChildAt(actNdx);
                 if (activity.app == app && activity.isDestroyable()) {
                     if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + activity
                             + " in state " + activity.getState() + " resumed=" + mResumedActivity
                             + " pausing=" + mPausingActivity + " for reason " + reason);
                     activity.destroyImmediately(true /* removeFromApp */, reason);
-                    if (activities.get(actNdx) != activity) {
+                    if (task.getChildAt(actNdx) != activity) {
                         // Was removed from list, back up so we don't miss the next one.
                         actNdx--;
                     }
@@ -4170,8 +4160,8 @@
 
         if (timeTracker != null) {
             // The caller wants a time tracker associated with this task.
-            for (int i = tr.mActivities.size() - 1; i >= 0; i--) {
-                tr.mActivities.get(i).appTimeTracker = timeTracker;
+            for (int i = tr.getChildCount() - 1; i >= 0; i--) {
+                tr.getChildAt(i).appTimeTracker = timeTracker;
             }
         }
 
@@ -4352,7 +4342,7 @@
             return;
         }
 
-        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "stack.resize_" + mStackId);
+        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "stack.resize_" + mStackId);
         mService.deferWindowLayout();
         try {
             // Update override configurations of all tasks in the stack.
@@ -4378,7 +4368,7 @@
             }
         } finally {
             mService.continueWindowLayout();
-            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         }
     }
 
@@ -4425,9 +4415,9 @@
 
     boolean willActivityBeVisibleLocked(IBinder token) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
+            final TaskRecord task = mTaskHistory.get(taskNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 if (r.appToken == token) {
                     return true;
                 }
@@ -4447,9 +4437,9 @@
 
     void closeSystemDialogsLocked() {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
+            final TaskRecord task = mTaskHistory.get(taskNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
                     r.finishIfPossible("close-sys", true /* oomAdj */);
                 }
@@ -4556,10 +4546,10 @@
         final int top = mTaskHistory.size() - 1;
         if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Performing unhandledBack(): top activity at " + top);
         if (top >= 0) {
-            final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities;
-            int activityTop = activities.size() - 1;
+            final TaskRecord task = mTaskHistory.get(top);
+            int activityTop = task.getChildCount() - 1;
             if (activityTop >= 0) {
-                activities.get(activityTop).finishIfPossible("unhandled-back", true /* oomAdj */);
+                task.getChildAt(activityTop).finishIfPossible("unhandled-back", true /* oomAdj */);
             }
         }
     }
@@ -4585,9 +4575,9 @@
 
     void handleAppCrash(WindowProcessController app) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
+            final TaskRecord task = mTaskHistory.get(taskNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = task.getChildAt(activityNdx);
                 if (r.app == app) {
                     Slog.w(TAG, "  Force finishing activity "
                             + r.intent.getComponent().flattenToShortString());
@@ -4705,9 +4695,9 @@
         // All activities that came from the package must be
         // restarted as if there was a config change.
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
-            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord a = activities.get(activityNdx);
+            final TaskRecord task = mTaskHistory.get(taskNdx);
+            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord a = task.getChildAt(activityNdx);
                 if (a.info.packageName.equals(packageName)) {
                     a.forceNewConfig = true;
                     if (starting != null && a == starting && a.visible) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index f1284d81..1bc36bb 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -44,7 +44,7 @@
 import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
 import static android.os.Process.INVALID_UID;
 import static android.os.Process.SYSTEM_UID;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.Display.TYPE_VIRTUAL;
@@ -690,7 +690,7 @@
     ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags,
             int filterCallingUid) {
         try {
-            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "resolveIntent");
+            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resolveIntent");
             int modifiedFlags = flags
                     | PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS;
             if (intent.isWebIntent()
@@ -711,7 +711,7 @@
                 Binder.restoreCallingIdentity(token);
             }
         } finally {
-            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         }
     }
 
@@ -824,7 +824,7 @@
                         System.identityHashCode(r), task.mTaskId, r.shortComponentName);
                 if (r.isActivityTypeHome()) {
                     // Home process is the root process of the task.
-                    updateHomeProcess(task.mActivities.get(0).app);
+                    updateHomeProcess(task.getChildAt(0).app);
                 }
                 mService.getPackageManagerInternalLocked().notifyPackageUse(
                         r.intent.getComponent().getPackageName(), NOTIFY_PACKAGE_USE_ACTIVITY);
@@ -1169,7 +1169,8 @@
             return ACTIVITY_RESTRICTION_NONE;
         }
 
-        if (mService.getAppOpsService().noteOperation(opCode, callingUid, callingPackage)
+        // TODO moltmann b/136595429: Set featureId from caller
+        if (mService.getAppOpsService().noteOperation(opCode, callingUid, callingPackage, /* featureId */ null)
                 != AppOpsManager.MODE_ALLOWED) {
             if (!ignoreTargetSecurity) {
                 return ACTIVITY_RESTRICTION_APPOP;
@@ -1212,7 +1213,8 @@
             return ACTIVITY_RESTRICTION_NONE;
         }
 
-        if (mService.getAppOpsService().noteOperation(opCode, callingUid, callingPackage)
+        // TODO moltmann b/136595429: Set componentId from caller
+        if (mService.getAppOpsService().noteOperation(opCode, callingUid, callingPackage, /* featureId */ null)
                 != AppOpsManager.MODE_ALLOWED) {
             return ACTIVITY_RESTRICTION_APPOP;
         }
@@ -1629,7 +1631,7 @@
             mPendingTempOtherTaskInsetBounds = copyOrNull(tempOtherTaskInsetBounds);
         }
 
-        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeDockedStack");
+        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizeDockedStack");
         mService.deferWindowLayout();
         try {
             // Don't allow re-entry while resizing. E.g. due to docked stack detaching.
@@ -1695,7 +1697,7 @@
         } finally {
             mAllowDockedStackResize = true;
             mService.continueWindowLayout();
-            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         }
     }
 
@@ -1717,7 +1719,7 @@
             return;
         }
 
-        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizePinnedStack");
+        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizePinnedStack");
         mService.deferWindowLayout();
         try {
             Rect insetBounds = null;
@@ -1739,7 +1741,7 @@
                     !DEFER_RESUME);
         } finally {
             mService.continueWindowLayout();
-            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         }
     }
 
@@ -1796,6 +1798,7 @@
             tr.removeTaskActivitiesLocked(reason);
             cleanUpRemovedTaskLocked(tr, killProcess, removeFromRecents);
             mService.getLockTaskController().clearLockedTask(tr);
+            mService.getTaskChangeNotificationController().notifyTaskStackChanged();
             if (tr.isPersistable) {
                 mService.notifyTaskPersisterLocked(null, true);
             }
@@ -1899,9 +1902,9 @@
         task.createTask(onTop, true /* showForAllUsers */);
         if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
                 "Added restored task=" + task + " to stack=" + stack);
-        final ArrayList<ActivityRecord> activities = task.mActivities;
-        for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-            activities.get(activityNdx).setTask(task);
+        for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+            final ActivityRecord r = task.getChildAt(activityNdx);
+            r.setTask(task);
         }
         return true;
     }
@@ -2253,7 +2256,7 @@
             pw.print(" #"); pw.print(i); pw.print(": ");
             pw.println(r);
             if (full) {
-                r.dump(pw, innerPrefix);
+                r.dump(pw, innerPrefix, true /* dumpAll */);
             } else if (complete) {
                 // Complete + brief == give a summary.  Isn't that obvious?!?
                 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
@@ -2501,8 +2504,8 @@
             return;
         }
 
-        for (int i = task.mActivities.size() - 1; i >= 0; i--) {
-            final ActivityRecord r = task.mActivities.get(i);
+        for (int i = task.getChildCount() - 1; i >= 0; i--) {
+            final ActivityRecord r = task.getChildAt(i);
             if (r.attachedToProcess()) {
                 mMultiWindowModeChangedActivities.add(r);
             }
@@ -2524,8 +2527,8 @@
     }
 
     void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, Rect targetStackBounds) {
-        for (int i = task.mActivities.size() - 1; i >= 0; i--) {
-            final ActivityRecord r = task.mActivities.get(i);
+        for (int i = task.getChildCount() - 1; i >= 0; i--) {
+            final ActivityRecord r = task.getChildAt(i);
             if (r.attachedToProcess()) {
                 mPipModeChangedActivities.add(r);
                 // If we are scheduling pip change, then remove this activity from multi-window
@@ -2543,8 +2546,8 @@
 
     void updatePictureInPictureMode(TaskRecord task, Rect targetStackBounds, boolean forceUpdate) {
         mHandler.removeMessages(REPORT_PIP_MODE_CHANGED_MSG);
-        for (int i = task.mActivities.size() - 1; i >= 0; i--) {
-            final ActivityRecord r = task.mActivities.get(i);
+        for (int i = task.getChildCount() - 1; i >= 0; i--) {
+            final ActivityRecord r = task.getChildAt(i);
             if (r.attachedToProcess()) {
                 r.updatePictureInPictureMode(targetStackBounds, forceUpdate);
             }
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 6ee64f3..63cec1a 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -506,7 +506,7 @@
         if (mLastHomeActivityStartRecord != null) {
             pw.print(prefix);
             pw.println("mLastHomeActivityStartRecord:");
-            mLastHomeActivityStartRecord.dump(pw, prefix + "  ");
+            mLastHomeActivityStartRecord.dump(pw, prefix + "  ", true /* dumpAll */);
         }
 
         final boolean dumpPackagePresent = dumpPackage != null;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 9397893..b793b39 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -770,13 +770,13 @@
         boolean restrictedBgActivity = false;
         if (!abort) {
             try {
-                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
                         "shouldAbortBackgroundActivityStart");
                 restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
                         callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
                         originatingPendingIntent, allowBackgroundActivityStart, intent);
             } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
             }
         }
 
@@ -1401,41 +1401,12 @@
         final ActivityStack startedActivityStack;
         try {
             mService.deferWindowLayout();
-            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
+            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
+            result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                     startFlags, doResume, options, inTask, outActivity, restrictedBgActivity);
         } finally {
-            final ActivityStack currentStack = r.getActivityStack();
-            startedActivityStack = currentStack != null ? currentStack : mTargetStack;
-
-            if (ActivityManager.isStartResultSuccessful(result)) {
-                if (startedActivityStack != null) {
-                    // If there is no state change (e.g. a resumed activity is reparented to
-                    // top of another display) to trigger a visibility/configuration checking,
-                    // we have to update the configuration for changing to different display.
-                    final ActivityRecord currentTop =
-                            startedActivityStack.topRunningActivityLocked();
-                    if (currentTop != null && currentTop.shouldUpdateConfigForDisplayChanged()) {
-                        mRootActivityContainer.ensureVisibilityAndConfig(
-                                currentTop, currentTop.getDisplayId(),
-                                true /* markFrozenIfConfigChanged */, false /* deferResume */);
-                    }
-                }
-            } else {
-                // If we are not able to proceed, disassociate the activity from the task.
-                // Leaving an activity in an incomplete state can lead to issues, such as
-                // performing operations without a window container.
-                final ActivityStack stack = mStartActivity.getActivityStack();
-                if (stack != null) {
-                    mStartActivity.finishIfPossible("startActivity", true /* oomAdj */);
-                }
-
-                // Stack should also be detached from display and be removed if it's empty.
-                if (startedActivityStack != null && startedActivityStack.isAttached()
-                        && startedActivityStack.numActivities() == 0
-                        && !startedActivityStack.isActivityTypeHome()) {
-                    startedActivityStack.remove();
-                }
-            }
+            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+            startedActivityStack = handleStartResult(r, result);
             mService.continueWindowLayout();
         }
 
@@ -1445,6 +1416,49 @@
     }
 
     /**
+     * If the start result is success, ensure that the configuration of the started activity matches
+     * the current display. Otherwise clean up unassociated containers to avoid leakage.
+     *
+     * @return the stack where the successful started activity resides.
+     */
+    private @Nullable ActivityStack handleStartResult(@NonNull ActivityRecord started, int result) {
+        final ActivityStack currentStack = started.getActivityStack();
+        ActivityStack startedActivityStack = currentStack != null ? currentStack : mTargetStack;
+
+        if (ActivityManager.isStartResultSuccessful(result)) {
+            if (startedActivityStack != null) {
+                // If there is no state change (e.g. a resumed activity is reparented to top of
+                // another display) to trigger a visibility/configuration checking, we have to
+                // update the configuration for changing to different display.
+                final ActivityRecord currentTop = startedActivityStack.topRunningActivityLocked();
+                if (currentTop != null && currentTop.shouldUpdateConfigForDisplayChanged()) {
+                    mRootActivityContainer.ensureVisibilityAndConfig(
+                            currentTop, currentTop.getDisplayId(),
+                            true /* markFrozenIfConfigChanged */, false /* deferResume */);
+                }
+            }
+            return startedActivityStack;
+        }
+
+        // If we are not able to proceed, disassociate the activity from the task. Leaving an
+        // activity in an incomplete state can lead to issues, such as performing operations
+        // without a window container.
+        final ActivityStack stack = mStartActivity.getActivityStack();
+        if (stack != null) {
+            mStartActivity.finishIfPossible("startActivity", true /* oomAdj */);
+        }
+
+        // Stack should also be detached from display and be removed if it's empty.
+        if (startedActivityStack != null && startedActivityStack.isAttached()
+                && startedActivityStack.numActivities() == 0
+                && !startedActivityStack.isActivityTypeHome()) {
+            startedActivityStack.remove();
+            startedActivityStack = null;
+        }
+        return startedActivityStack;
+    }
+
+    /**
      * Return true if background activity is really aborted.
      *
      * TODO(b/131748165): Refactor the logic so we don't need to call this method everywhere.
@@ -1469,7 +1483,7 @@
     }
 
     // Note: This method should only be called from {@link startActivity}.
-    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
+    private int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
             int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
             ActivityRecord[] outActivity, boolean restrictedBgActivity) {
@@ -1592,7 +1606,7 @@
                 // accordingly.
                 if (mTargetStack.isFocusable()
                         && !mRootActivityContainer.isTopDisplayFocusedStack(mTargetStack)) {
-                    mTargetStack.moveToFront("startActivityUnchecked");
+                    mTargetStack.moveToFront("startActivityInner");
                 }
                 mRootActivityContainer.resumeFocusedStacksTopActivities(
                         mTargetStack, mStartActivity, mOptions);
@@ -1820,7 +1834,9 @@
      */
     private void complyActivityFlags(TaskRecord targetTask, ActivityRecord reusedActivity) {
         ActivityRecord targetTaskTop = targetTask.getTopActivity();
-        if (reusedActivity != null && (mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
+        final boolean resetTask =
+                reusedActivity != null && (mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0;
+        if (resetTask) {
             targetTaskTop = mTargetStack.resetTaskIfNeededLocked(targetTaskTop, mStartActivity);
         }
 
@@ -1873,7 +1889,7 @@
                     mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
                             mLaunchFlags, mOptions);
                     mTargetStack.addTask(targetTask,
-                            !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
+                            !mLaunchTaskBehind /* toTop */, "complyActivityFlags");
                 }
             }
         } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) == 0 && !mAddingToTask
@@ -1893,14 +1909,17 @@
                 mAddingToTask = true;
             }
         } else if (mStartActivity.mActivityComponent.equals(targetTask.realActivity)) {
-            // In this case the top activity on the task is the same as the one being launched,
-            // so we take that as a request to bring the task to the foreground. If the top
-            // activity in the task is the root activity, deliver this new intent to it if it
-            // desires.
-            if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
-                    || LAUNCH_SINGLE_TOP == mLaunchMode)
-                    && targetTaskTop.mActivityComponent.equals(
-                    mStartActivity.mActivityComponent) && mStartActivity.resultTo == null) {
+            if (targetTask == mInTask) {
+                // In this case we are bringing up an existing activity from a recent task. We
+                // don't need to add a new activity instance on top.
+            } else if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
+                            || LAUNCH_SINGLE_TOP == mLaunchMode)
+                    && targetTaskTop.mActivityComponent.equals(mStartActivity.mActivityComponent)
+                    && mStartActivity.resultTo == null) {
+                // In this case the top activity on the task is the same as the one being launched,
+                // so we take that as a request to bring the task to the foreground. If the top
+                // activity in the task is the root activity, deliver this new intent to it if it
+                // desires.
                 if (targetTaskTop.isRootOfTask()) {
                     targetTaskTop.getTaskRecord().setIntent(mStartActivity);
                 }
@@ -1912,7 +1931,7 @@
             } else if (reusedActivity == null) {
                 mAddingToTask = true;
             }
-        } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
+        } else if (!resetTask) {
             // In this case an activity is being launched in to an existing task, without
             // resetting that task. This is typically the situation of launching an activity
             // from a notification or shortcut. We want to place the new activity on top of the
@@ -2430,7 +2449,7 @@
         if (mStartActivity.getTaskRecord() == null || mStartActivity.getTaskRecord() == parent) {
             parent.addActivityToTop(mStartActivity);
         } else {
-            mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
+            mStartActivity.reparent(parent, parent.getChildCount() /* top */, reason);
         }
     }
 
@@ -2827,12 +2846,12 @@
         if (r != null) {
             pw.print(prefix);
             pw.println("mLastStartActivityRecord:");
-            r.dump(pw, prefix + "  ");
+            r.dump(pw, prefix + "  ", true /* dumpAll */);
         }
         if (mStartActivity != null) {
             pw.print(prefix);
             pw.println("mStartActivity:");
-            mStartActivity.dump(pw, prefix + "  ");
+            mStartActivity.dump(pw, prefix + "  ", true /* dumpAll */);
         }
         if (mIntent != null) {
             pw.print(prefix);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index ab35652..0488a3b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -159,10 +159,10 @@
      *
      * @param reasons A map from windowing mode to a reason integer why the transition was started,
      *                which must be one of the APP_TRANSITION_* values.
-     * @param timestamp The time at which the app transition started in
-     *                  {@link SystemClock#uptimeMillis()} timebase.
+     * @param timestampNs The time at which the app transition started in
+     *                  {@link SystemClock#elapsedRealtimeNs()} ()} timebase.
      */
-    public abstract void notifyAppTransitionStarting(SparseIntArray reasons, long timestamp);
+    public abstract void notifyAppTransitionStarting(SparseIntArray reasons, long timestampNs);
 
     /**
      * Callback for window manager to let activity manager know that the app transition was
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 9b9dc88..14df505 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -52,7 +52,7 @@
 import static android.os.FactoryTest.FACTORY_TEST_OFF;
 import static android.os.Process.FIRST_APPLICATION_UID;
 import static android.os.Process.SYSTEM_UID;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
@@ -886,7 +886,7 @@
 
     boolean hasSystemAlertWindowPermission(int callingUid, int callingPid, String callingPackage) {
         final int mode = getAppOpsService().noteOperation(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
-                callingUid, callingPackage);
+                callingUid, callingPackage, /* featureId */ null);
         if (mode == AppOpsManager.MODE_DEFAULT) {
             return checkPermission(Manifest.permission.SYSTEM_ALERT_WINDOW, callingPid, callingUid)
                     == PERMISSION_GRANTED;
@@ -1606,6 +1606,7 @@
             }
 
             final long origId = Binder.clearCallingIdentity();
+            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "finishActivity");
             try {
                 boolean res;
                 final boolean finishWithRootActivity =
@@ -1633,6 +1634,7 @@
                 }
                 return res;
             } finally {
+                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                 Binder.restoreCallingIdentity(origId);
             }
         }
@@ -1667,6 +1669,7 @@
         try {
             WindowProcessController proc = null;
             synchronized (mGlobalLock) {
+                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityIdle");
                 ActivityStack stack = ActivityRecord.getStackLocked(token);
                 if (stack == null) {
                     return;
@@ -1681,6 +1684,7 @@
                 }
             }
         } finally {
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
             Binder.restoreCallingIdentity(origId);
         }
     }
@@ -1707,10 +1711,12 @@
     public final void activityPaused(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         synchronized (mGlobalLock) {
+            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused");
             ActivityStack stack = ActivityRecord.getStackLocked(token);
             if (stack != null) {
                 stack.activityPausedLocked(token, false);
             }
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         }
         Binder.restoreCallingIdentity(origId);
     }
@@ -1731,6 +1737,7 @@
         int restartingUid = 0;
         final ActivityRecord r;
         synchronized (mGlobalLock) {
+            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityStopped");
             r = ActivityRecord.isInStackLocked(token);
             if (r != null) {
                 if (r.attachedToProcess()
@@ -1742,6 +1749,7 @@
                 }
                 r.activityStoppedLocked(icicle, persistentState, description);
             }
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         }
 
         if (restartingName != null) {
@@ -1763,12 +1771,14 @@
         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "ACTIVITY DESTROYED: " + token);
         synchronized (mGlobalLock) {
             final long origId = Binder.clearCallingIdentity();
+            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityDestroyed");
             try {
                 final ActivityRecord activity = ActivityRecord.forTokenLocked(token);
                 if (activity != null) {
                     activity.destroyed("activityDestroyed");
                 }
             } finally {
+                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                 Binder.restoreCallingIdentity(origId);
             }
         }
@@ -1981,7 +1991,7 @@
                 final TaskRecord task = r.getTaskRecord();
                 int index = task.mActivities.lastIndexOf(r);
                 if (index > 0) {
-                    ActivityRecord under = task.mActivities.get(index - 1);
+                    ActivityRecord under = task.getChildAt(index - 1);
                     under.returningOptions = safeOptions != null ? safeOptions.getOptions(r) : null;
                 }
                 return r.setOccludesParent(false);
@@ -4974,7 +4984,7 @@
                 pw.println("(not running)");
             }
             if (dumpAll) {
-                r.dump(pw, innerPrefix);
+                r.dump(pw, innerPrefix, true /* dumpAll */);
             }
         }
         if (appThread != null) {
@@ -5506,8 +5516,8 @@
     void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
             String hostingType) {
         try {
-            if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) {
-                Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
+            if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
+                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"
                         + activity.processName);
             }
             // Post message to start process to avoid possible deadlock of calling into AMS with the
@@ -5517,7 +5527,7 @@
                     isTop, hostingType, activity.intent.getComponent());
             mH.sendMessage(m);
         } finally {
-            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         }
     }
 
@@ -5670,11 +5680,11 @@
 
     private void updateResumedAppTrace(@Nullable ActivityRecord resumed) {
         if (mTracedResumedActivity != null) {
-            Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER,
+            Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER,
                     constructResumedTraceName(mTracedResumedActivity.packageName), 0);
         }
         if (resumed != null) {
-            Trace.asyncTraceBegin(TRACE_TAG_ACTIVITY_MANAGER,
+            Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER,
                     constructResumedTraceName(resumed.packageName), 0);
         }
         mTracedResumedActivity = resumed;
@@ -6002,10 +6012,10 @@
 
         @Override
         public void notifyAppTransitionStarting(SparseIntArray reasons,
-                long timestamp) {
+                long timestampNs) {
             synchronized (mGlobalLock) {
                 mStackSupervisor.getActivityMetricsLogger().notifyTransitionStarting(
-                        reasons, timestamp);
+                        reasons, timestampNs);
             }
         }
 
@@ -6773,7 +6783,14 @@
         @Override
         public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
             synchronized (mGlobalLockWithoutBoost) {
-                return mRootActivityContainer.attachApplication(wpc);
+                if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
+                    Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);
+                }
+                try {
+                    return mRootActivityContainer.attachApplication(wpc);
+                } finally {
+                    Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java b/services/core/java/com/android/server/wm/AnimatingActivityRegistry.java
similarity index 72%
rename from services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java
rename to services/core/java/com/android/server/wm/AnimatingActivityRegistry.java
index 9c00d1a..18ec96c 100644
--- a/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java
+++ b/services/core/java/com/android/server/wm/AnimatingActivityRegistry.java
@@ -23,55 +23,55 @@
 import java.util.ArrayList;
 
 /**
- * Keeps track of all {@link AppWindowToken} that are animating and makes sure all animations are
+ * Keeps track of all {@link ActivityRecord} that are animating and makes sure all animations are
  * finished at the same time such that we don't run into issues with z-ordering: An activity A
  * that has a shorter animation that is above another activity B with a longer animation in the same
  * task, the animation layer would put the B on top of A, but from the hierarchy, A needs to be on
  * top of B. Thus, we defer reparenting A to the original hierarchy such that it stays on top of B
  * until B finishes animating.
  */
-class AnimatingAppWindowTokenRegistry {
+class AnimatingActivityRegistry {
 
-    private ArraySet<AppWindowToken> mAnimatingTokens = new ArraySet<>();
-    private ArrayMap<AppWindowToken, Runnable> mFinishedTokens = new ArrayMap<>();
+    private ArraySet<ActivityRecord> mAnimatingActivities = new ArraySet<>();
+    private ArrayMap<ActivityRecord, Runnable> mFinishedTokens = new ArrayMap<>();
 
     private ArrayList<Runnable> mTmpRunnableList = new ArrayList<>();
 
     private boolean mEndingDeferredFinish;
 
     /**
-     * Notifies that an {@link AppWindowToken} has started animating.
+     * Notifies that an {@link ActivityRecord} has started animating.
      */
-    void notifyStarting(AppWindowToken token) {
-        mAnimatingTokens.add(token);
+    void notifyStarting(ActivityRecord token) {
+        mAnimatingActivities.add(token);
     }
 
     /**
-     * Notifies that an {@link AppWindowToken} has finished animating.
+     * Notifies that an {@link ActivityRecord} has finished animating.
      */
-    void notifyFinished(AppWindowToken token) {
-        mAnimatingTokens.remove(token);
-        mFinishedTokens.remove(token);
+    void notifyFinished(ActivityRecord activity) {
+        mAnimatingActivities.remove(activity);
+        mFinishedTokens.remove(activity);
 
-        // If we were the last token, make sure the end all deferred finishes.
-        if (mAnimatingTokens.isEmpty()) {
+        // If we were the last activity, make sure the end all deferred finishes.
+        if (mAnimatingActivities.isEmpty()) {
             endDeferringFinished();
         }
     }
 
     /**
-     * Called when an {@link AppWindowToken} is about to finish animating.
+     * Called when an {@link ActivityRecord} is about to finish animating.
      *
      * @param endDeferFinishCallback Callback to run when defer finish should be ended.
      * @return {@code true} if finishing the animation should be deferred, {@code false} otherwise.
      */
-    boolean notifyAboutToFinish(AppWindowToken token, Runnable endDeferFinishCallback) {
-        final boolean removed = mAnimatingTokens.remove(token);
+    boolean notifyAboutToFinish(ActivityRecord activity, Runnable endDeferFinishCallback) {
+        final boolean removed = mAnimatingActivities.remove(activity);
         if (!removed) {
             return false;
         }
 
-        if (mAnimatingTokens.isEmpty()) {
+        if (mAnimatingActivities.isEmpty()) {
 
             // If no animations are animating anymore, finish all others.
             endDeferringFinished();
@@ -79,7 +79,7 @@
         } else {
 
             // Otherwise let's put it into the pending list of to be finished animations.
-            mFinishedTokens.put(token, endDeferFinishCallback);
+            mFinishedTokens.put(activity, endDeferFinishCallback);
             return true;
         }
     }
@@ -110,10 +110,10 @@
     }
 
     void dump(PrintWriter pw, String header, String prefix) {
-        if (!mAnimatingTokens.isEmpty() || !mFinishedTokens.isEmpty()) {
+        if (!mAnimatingActivities.isEmpty() || !mFinishedTokens.isEmpty()) {
             pw.print(prefix); pw.println(header);
             prefix = prefix + "  ";
-            pw.print(prefix); pw.print("mAnimatingTokens="); pw.println(mAnimatingTokens);
+            pw.print(prefix); pw.print("mAnimatingActivities="); pw.println(mAnimatingActivities);
             pw.print(prefix); pw.print("mFinishedTokens="); pw.println(mFinishedTokens);
         }
     }
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 394b475..c1143c8 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -338,8 +338,8 @@
         updateBooster();
     }
 
-    void setLastAppTransition(int transit, AppWindowToken openingApp, AppWindowToken closingApp,
-            AppWindowToken changingApp) {
+    void setLastAppTransition(int transit, ActivityRecord openingApp, ActivityRecord closingApp,
+            ActivityRecord changingApp) {
         mLastUsedAppTransition = transit;
         mLastOpeningApp = "" + openingApp;
         mLastClosingApp = "" + closingApp;
@@ -430,7 +430,7 @@
      * @return bit-map of WindowManagerPolicy#FINISH_LAYOUT_REDO_* to indicate whether another
      *         layout pass needs to be done
      */
-    int goodToGo(int transit, AppWindowToken topOpeningApp, ArraySet<AppWindowToken> openingApps) {
+    int goodToGo(int transit, ActivityRecord topOpeningApp, ArraySet<ActivityRecord> openingApps) {
         mNextAppTransition = TRANSIT_UNSET;
         mNextAppTransitionFlags = 0;
         setAppTransitionState(APP_STATE_RUNNING);
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 894dfd4..3bda0c2 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -156,20 +156,20 @@
         final ArraySet<Integer> activityTypes = collectActivityTypes(mDisplayContent.mOpeningApps,
                 mDisplayContent.mClosingApps, mDisplayContent.mChangingApps);
         final boolean allowAnimations = mDisplayContent.getDisplayPolicy().allowAppAnimationsLw();
-        final AppWindowToken animLpToken = allowAnimations
+        final ActivityRecord animLpActivity = allowAnimations
                 ? findAnimLayoutParamsToken(transit, activityTypes)
                 : null;
-        final AppWindowToken topOpeningApp = allowAnimations
+        final ActivityRecord topOpeningApp = allowAnimations
                 ? getTopApp(mDisplayContent.mOpeningApps, false /* ignoreHidden */)
                 : null;
-        final AppWindowToken topClosingApp = allowAnimations
+        final ActivityRecord topClosingApp = allowAnimations
                 ? getTopApp(mDisplayContent.mClosingApps, false /* ignoreHidden */)
                 : null;
-        final AppWindowToken topChangingApp = allowAnimations
+        final ActivityRecord topChangingApp = allowAnimations
                 ? getTopApp(mDisplayContent.mChangingApps, false /* ignoreHidden */)
                 : null;
-        final WindowManager.LayoutParams animLp = getAnimLp(animLpToken);
-        overrideWithRemoteAnimationIfSet(animLpToken, transit, activityTypes);
+        final WindowManager.LayoutParams animLp = getAnimLp(animLpActivity);
+        overrideWithRemoteAnimationIfSet(animLpActivity, transit, activityTypes);
 
         final boolean voiceInteraction = containsVoiceInteraction(mDisplayContent.mOpeningApps)
                 || containsVoiceInteraction(mDisplayContent.mOpeningApps)
@@ -209,7 +209,7 @@
         mDisplayContent.computeImeTarget(true /* updateImeTarget */);
 
         mService.mAtmInternal.notifyAppTransitionStarting(mTempTransitionReasons.clone(),
-                SystemClock.uptimeMillis());
+            SystemClock.elapsedRealtimeNanos());
 
         if (transit == TRANSIT_SHOW_SINGLE_TASK_DISPLAY) {
             mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
@@ -223,14 +223,14 @@
                 layoutRedo | FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG;
     }
 
-    private static WindowManager.LayoutParams getAnimLp(AppWindowToken wtoken) {
-        final WindowState mainWindow = wtoken != null ? wtoken.findMainWindow() : null;
+    private static WindowManager.LayoutParams getAnimLp(ActivityRecord activity) {
+        final WindowState mainWindow = activity != null ? activity.findMainWindow() : null;
         return mainWindow != null ? mainWindow.mAttrs : null;
     }
 
-    RemoteAnimationAdapter getRemoteAnimationOverride(AppWindowToken animLpToken, int transit,
+    RemoteAnimationAdapter getRemoteAnimationOverride(ActivityRecord animLpActivity, int transit,
             ArraySet<Integer> activityTypes) {
-        final RemoteAnimationDefinition definition = animLpToken.getRemoteAnimationDefinition();
+        final RemoteAnimationDefinition definition = animLpActivity.getRemoteAnimationDefinition();
         if (definition != null) {
             final RemoteAnimationAdapter adapter = definition.getAdapter(transit, activityTypes);
             if (adapter != null) {
@@ -247,19 +247,19 @@
      * Overrides the pending transition with the remote animation defined for the transition in the
      * set of defined remote animations in the app window token.
      */
-    private void overrideWithRemoteAnimationIfSet(AppWindowToken animLpToken, int transit,
+    private void overrideWithRemoteAnimationIfSet(ActivityRecord animLpActivity, int transit,
             ArraySet<Integer> activityTypes) {
         if (transit == TRANSIT_CRASHING_ACTIVITY_CLOSE) {
             // The crash transition has higher priority than any involved remote animations.
             return;
         }
-        if (animLpToken == null) {
+        if (animLpActivity == null) {
             return;
         }
         final RemoteAnimationAdapter adapter =
-                getRemoteAnimationOverride(animLpToken, transit, activityTypes);
+                getRemoteAnimationOverride(animLpActivity, transit, activityTypes);
         if (adapter != null) {
-            animLpToken.getDisplayContent().mAppTransition.overridePendingAppTransitionRemote(
+            animLpActivity.getDisplayContent().mAppTransition.overridePendingAppTransitionRemote(
                     adapter);
         }
     }
@@ -267,12 +267,12 @@
     /**
      * @return The window token that determines the animation theme.
      */
-    private AppWindowToken findAnimLayoutParamsToken(@WindowManager.TransitionType int transit,
+    private ActivityRecord findAnimLayoutParamsToken(@WindowManager.TransitionType int transit,
             ArraySet<Integer> activityTypes) {
-        AppWindowToken result;
-        final ArraySet<AppWindowToken> closingApps = mDisplayContent.mClosingApps;
-        final ArraySet<AppWindowToken> openingApps = mDisplayContent.mOpeningApps;
-        final ArraySet<AppWindowToken> changingApps = mDisplayContent.mChangingApps;
+        ActivityRecord result;
+        final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
+        final ArraySet<ActivityRecord> openingApps = mDisplayContent.mOpeningApps;
+        final ArraySet<ActivityRecord> changingApps = mDisplayContent.mChangingApps;
 
         // Remote animations always win, but fullscreen tokens override non-fullscreen tokens.
         result = lookForHighestTokenWithFilter(closingApps, openingApps, changingApps,
@@ -294,8 +294,8 @@
      * @return The set of {@link android.app.WindowConfiguration.ActivityType}s contained in the set
      *         of apps in {@code array1}, {@code array2}, and {@code array3}.
      */
-    private static ArraySet<Integer> collectActivityTypes(ArraySet<AppWindowToken> array1,
-            ArraySet<AppWindowToken> array2, ArraySet<AppWindowToken> array3) {
+    private static ArraySet<Integer> collectActivityTypes(ArraySet<ActivityRecord> array1,
+            ArraySet<ActivityRecord> array2, ArraySet<ActivityRecord> array3) {
         final ArraySet<Integer> result = new ArraySet<>();
         for (int i = array1.size() - 1; i >= 0; i--) {
             result.add(array1.valueAt(i).getActivityType());
@@ -309,16 +309,16 @@
         return result;
     }
 
-    private static AppWindowToken lookForHighestTokenWithFilter(ArraySet<AppWindowToken> array1,
-            ArraySet<AppWindowToken> array2, ArraySet<AppWindowToken> array3,
-            Predicate<AppWindowToken> filter) {
+    private static ActivityRecord lookForHighestTokenWithFilter(ArraySet<ActivityRecord> array1,
+            ArraySet<ActivityRecord> array2, ArraySet<ActivityRecord> array3,
+            Predicate<ActivityRecord> filter) {
         final int array2base = array1.size();
         final int array3base = array2.size() + array2base;
         final int count = array3base + array3.size();
         int bestPrefixOrderIndex = Integer.MIN_VALUE;
-        AppWindowToken bestToken = null;
+        ActivityRecord bestToken = null;
         for (int i = 0; i < count; i++) {
-            final AppWindowToken wtoken = i < array2base
+            final ActivityRecord wtoken = i < array2base
                     ? array1.valueAt(i)
                     : (i < array3base
                             ? array2.valueAt(i - array2base)
@@ -332,7 +332,7 @@
         return bestToken;
     }
 
-    private boolean containsVoiceInteraction(ArraySet<AppWindowToken> apps) {
+    private boolean containsVoiceInteraction(ArraySet<ActivityRecord> apps) {
         for (int i = apps.size() - 1; i >= 0; i--) {
             if (apps.valueAt(i).mVoiceInteraction) {
                 return true;
@@ -342,10 +342,10 @@
     }
 
     private void handleOpeningApps(int transit, LayoutParams animLp, boolean voiceInteraction) {
-        final ArraySet<AppWindowToken> openingApps = mDisplayContent.mOpeningApps;
+        final ArraySet<ActivityRecord> openingApps = mDisplayContent.mOpeningApps;
         final int appsCount = openingApps.size();
         for (int i = 0; i < appsCount; i++) {
-            AppWindowToken wtoken = openingApps.valueAt(i);
+            ActivityRecord wtoken = openingApps.valueAt(i);
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now opening app %s", wtoken);
 
             if (!wtoken.commitVisibility(animLp, true, transit, false, voiceInteraction)) {
@@ -376,10 +376,10 @@
     }
 
     private void handleClosingApps(int transit, LayoutParams animLp, boolean voiceInteraction) {
-        final ArraySet<AppWindowToken> closingApps = mDisplayContent.mClosingApps;
+        final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
         final int appsCount = closingApps.size();
         for (int i = 0; i < appsCount; i++) {
-            AppWindowToken wtoken = closingApps.valueAt(i);
+            ActivityRecord wtoken = closingApps.valueAt(i);
 
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now closing app %s", wtoken);
             // TODO: Do we need to add to mNoAnimationNotifyOnTransitionFinished like above if not
@@ -404,17 +404,17 @@
     }
 
     private void handleChangingApps(int transit, LayoutParams animLp, boolean voiceInteraction) {
-        final ArraySet<AppWindowToken> apps = mDisplayContent.mChangingApps;
+        final ArraySet<ActivityRecord> apps = mDisplayContent.mChangingApps;
         final int appsCount = apps.size();
         for (int i = 0; i < appsCount; i++) {
-            AppWindowToken wtoken = apps.valueAt(i);
-            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now changing app %s", wtoken);
-            wtoken.cancelAnimationOnly();
-            wtoken.applyAnimationLocked(null, transit, true, false);
-            wtoken.updateReportedVisibilityLocked();
+            ActivityRecord activity = apps.valueAt(i);
+            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now changing app %s", activity);
+            activity.cancelAnimationOnly();
+            activity.applyAnimationLocked(null, transit, true, false);
+            activity.updateReportedVisibilityLocked();
             mService.openSurfaceTransaction();
             try {
-                wtoken.showAllWindowsLocked();
+                activity.showAllWindowsLocked();
             } finally {
                 mService.closeSurfaceTransaction("handleChangingApps");
             }
@@ -442,7 +442,7 @@
         }
     }
 
-    private boolean transitionGoodToGo(ArraySet<AppWindowToken> apps, SparseIntArray outReasons) {
+    private boolean transitionGoodToGo(ArraySet<ActivityRecord> apps, SparseIntArray outReasons) {
         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                 "Checking %d opening apps (frozen=%b timeout=%b)...", apps.size(),
                 mService.mDisplayFrozen, mDisplayContent.mAppTransition.isTimeout());
@@ -465,25 +465,25 @@
                 return false;
             }
             for (int i = 0; i < apps.size(); i++) {
-                AppWindowToken wtoken = apps.valueAt(i);
+                ActivityRecord activity = apps.valueAt(i);
                 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                                 "Check opening app=%s: allDrawn=%b startingDisplayed=%b "
                                         + "startingMoved=%b isRelaunching()=%b startingWindow=%s",
-                                wtoken, wtoken.allDrawn, wtoken.startingDisplayed,
-                                wtoken.startingMoved, wtoken.isRelaunching(),
-                                wtoken.startingWindow);
+                                activity, activity.allDrawn, activity.startingDisplayed,
+                                activity.startingMoved, activity.isRelaunching(),
+                                activity.startingWindow);
 
 
-                final boolean allDrawn = wtoken.allDrawn && !wtoken.isRelaunching();
-                if (!allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {
+                final boolean allDrawn = activity.allDrawn && !activity.isRelaunching();
+                if (!allDrawn && !activity.startingDisplayed && !activity.startingMoved) {
                     return false;
                 }
-                final int windowingMode = wtoken.getWindowingMode();
+                final int windowingMode = activity.getWindowingMode();
                 if (allDrawn) {
                     outReasons.put(windowingMode,  APP_TRANSITION_WINDOWS_DRAWN);
                 } else {
                     outReasons.put(windowingMode,
-                            wtoken.mStartingData instanceof SplashScreenStartingData
+                            activity.mStartingData instanceof SplashScreenStartingData
                                     ? APP_TRANSITION_SPLASH_SCREEN
                                     : APP_TRANSITION_SNAPSHOT);
                 }
@@ -534,11 +534,11 @@
                 (mWallpaperControllerLocked.isWallpaperTargetAnimating() || !showWallpaper)
                         ? null
                         : wallpaperTarget;
-        final ArraySet<AppWindowToken> openingApps = mDisplayContent.mOpeningApps;
-        final ArraySet<AppWindowToken> closingApps = mDisplayContent.mClosingApps;
-        final AppWindowToken topOpeningApp = getTopApp(mDisplayContent.mOpeningApps,
+        final ArraySet<ActivityRecord> openingApps = mDisplayContent.mOpeningApps;
+        final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
+        final ActivityRecord topOpeningApp = getTopApp(mDisplayContent.mOpeningApps,
                 false /* ignoreHidden */);
-        final AppWindowToken topClosingApp = getTopApp(mDisplayContent.mClosingApps,
+        final ActivityRecord topClosingApp = getTopApp(mDisplayContent.mClosingApps,
                 true /* ignoreHidden */);
 
         boolean openingCanBeWallpaperTarget = canBeWallpaperTarget(openingApps);
@@ -571,17 +571,17 @@
                 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                         "New transit: %s", AppTransition.appTransitionToString(transit));
             } else if (oldWallpaper != null && !mDisplayContent.mOpeningApps.isEmpty()
-                    && !openingApps.contains(oldWallpaper.mAppToken)
-                    && closingApps.contains(oldWallpaper.mAppToken)
-                    && topClosingApp == oldWallpaper.mAppToken) {
+                    && !openingApps.contains(oldWallpaper.mActivityRecord)
+                    && closingApps.contains(oldWallpaper.mActivityRecord)
+                    && topClosingApp == oldWallpaper.mActivityRecord) {
                 // We are transitioning from an activity with a wallpaper to one without.
                 transit = TRANSIT_WALLPAPER_CLOSE;
                 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                         "New transit away from wallpaper: %s",
                                 AppTransition.appTransitionToString(transit));
             } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw()
-                    && openingApps.contains(wallpaperTarget.mAppToken)
-                    && topOpeningApp == wallpaperTarget.mAppToken
+                    && openingApps.contains(wallpaperTarget.mActivityRecord)
+                    && topOpeningApp == wallpaperTarget.mActivityRecord
                     && transit != TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE) {
                 // We are transitioning from an activity without
                 // a wallpaper to now showing the wallpaper
@@ -616,10 +616,10 @@
         boolean allOpeningVisible = true;
         boolean allTranslucentOpeningApps = !mDisplayContent.mOpeningApps.isEmpty();
         for (int i = mDisplayContent.mOpeningApps.size() - 1; i >= 0; i--) {
-            final AppWindowToken token = mDisplayContent.mOpeningApps.valueAt(i);
-            if (!token.isVisible()) {
+            final ActivityRecord activity = mDisplayContent.mOpeningApps.valueAt(i);
+            if (!activity.isVisible()) {
                 allOpeningVisible = false;
-                if (token.fillsParent()) {
+                if (activity.fillsParent()) {
                     allTranslucentOpeningApps = false;
                 }
             }
@@ -660,13 +660,13 @@
             return false;
         }
         // check that all components are in the task.
-        for (AppWindowToken activity : mDisplayContent.mOpeningApps) {
+        for (ActivityRecord activity : mDisplayContent.mOpeningApps) {
             Task activityTask = activity.getTask();
             if (activityTask != task) {
                 return false;
             }
         }
-        for (AppWindowToken activity : mDisplayContent.mClosingApps) {
+        for (ActivityRecord activity : mDisplayContent.mClosingApps) {
             if (activity.getTask() != task) {
                 return false;
             }
@@ -674,7 +674,7 @@
         return true;
     }
 
-    private boolean canBeWallpaperTarget(ArraySet<AppWindowToken> apps) {
+    private boolean canBeWallpaperTarget(ArraySet<ActivityRecord> apps) {
         for (int i = apps.size() - 1; i >= 0; i--) {
             if (apps.valueAt(i).windowsCanBeWallpaperTarget()) {
                 return true;
@@ -684,18 +684,18 @@
     }
 
     /**
-     * Finds the top app in a list of apps, using its {@link AppWindowToken#getPrefixOrderIndex} to
+     * Finds the top app in a list of apps, using its {@link ActivityRecord#getPrefixOrderIndex} to
      * compare z-order.
      *
      * @param apps The list of apps to search.
-     * @param ignoreHidden If set to true, ignores apps that are {@link AppWindowToken#isHidden}.
-     * @return The top {@link AppWindowToken}.
+     * @param ignoreHidden If set to true, ignores apps that are {@link ActivityRecord#isHidden}.
+     * @return The top {@link ActivityRecord}.
      */
-    private AppWindowToken getTopApp(ArraySet<AppWindowToken> apps, boolean ignoreHidden) {
+    private ActivityRecord getTopApp(ArraySet<ActivityRecord> apps, boolean ignoreHidden) {
         int topPrefixOrderIndex = Integer.MIN_VALUE;
-        AppWindowToken topApp = null;
+        ActivityRecord topApp = null;
         for (int i = apps.size() - 1; i >= 0; i--) {
-            final AppWindowToken app = apps.valueAt(i);
+            final ActivityRecord app = apps.valueAt(i);
             if (ignoreHidden && app.isHidden()) {
                 continue;
             }
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index 2b05024..acd96e9 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -44,39 +44,39 @@
 import java.util.function.Supplier;
 
 /**
- * Represents a surface that is displayed over an {@link AppWindowToken}
+ * Represents a surface that is displayed over an {@link ActivityRecord}
  */
 class AppWindowThumbnail implements Animatable {
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowThumbnail" : TAG_WM;
 
-    private final AppWindowToken mAppToken;
+    private final ActivityRecord mActivityRecord;
     private SurfaceControl mSurfaceControl;
     private final SurfaceAnimator mSurfaceAnimator;
     private final int mWidth;
     private final int mHeight;
     private final boolean mRelative;
 
-    AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, AppWindowToken appToken,
+    AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, ActivityRecord activity,
             GraphicBuffer thumbnailHeader) {
-        this(surfaceFactory, t, appToken, thumbnailHeader, false /* relative */);
+        this(surfaceFactory, t, activity, thumbnailHeader, false /* relative */);
     }
 
     /**
      * @param t Transaction to create the thumbnail in.
-     * @param appToken {@link AppWindowToken} to associate this thumbnail with.
+     * @param activity {@link ActivityRecord} to associate this thumbnail with.
      * @param thumbnailHeader A thumbnail or placeholder for thumbnail to initialize with.
-     * @param relative Whether this thumbnail will be a child of appToken (and thus positioned
+     * @param relative Whether this thumbnail will be a child of activity (and thus positioned
      *                 relative to it) or not.
      */
-    AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, AppWindowToken appToken,
+    AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, ActivityRecord activity,
             GraphicBuffer thumbnailHeader, boolean relative) {
-        this(t, appToken, thumbnailHeader, relative, surfaceFactory.get(), null);
+        this(t, activity, thumbnailHeader, relative, surfaceFactory.get(), null);
     }
 
-    AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader,
+    AppWindowThumbnail(Transaction t, ActivityRecord activity, GraphicBuffer thumbnailHeader,
             boolean relative, Surface drawSurface, SurfaceAnimator animator) {
-        mAppToken = appToken;
+        mActivityRecord = activity;
         mRelative = relative;
         if (animator != null) {
             mSurfaceAnimator = animator;
@@ -84,22 +84,22 @@
             // We can't use a delegating constructor since we need to
             // reference this::onAnimationFinished
             mSurfaceAnimator =
-                new SurfaceAnimator(this, this::onAnimationFinished, appToken.mWmService);
+                new SurfaceAnimator(this, this::onAnimationFinished, activity.mWmService);
         }
         mWidth = thumbnailHeader.getWidth();
         mHeight = thumbnailHeader.getHeight();
 
         // Create a new surface for the thumbnail
-        WindowState window = appToken.findMainWindow();
+        WindowState window = mActivityRecord.findMainWindow();
 
         // TODO: This should be attached as a child to the app token, once the thumbnail animations
         // use relative coordinates. Once we start animating task we can also consider attaching
         // this to the task.
-        mSurfaceControl = appToken.makeSurface()
-                .setName("thumbnail anim: " + appToken.toString())
+        mSurfaceControl = mActivityRecord.makeSurface()
+                .setName("thumbnail anim: " + mActivityRecord.toString())
                 .setBufferSize(mWidth, mHeight)
                 .setFormat(PixelFormat.TRANSLUCENT)
-                .setMetadata(METADATA_WINDOW_TYPE, appToken.windowType)
+                .setMetadata(METADATA_WINDOW_TYPE, mActivityRecord.windowType)
                 .setMetadata(METADATA_OWNER_UID,
                         window != null ? window.mOwnerUid : Binder.getCallingUid())
                 .build();
@@ -116,7 +116,7 @@
         // task.
         t.setLayer(mSurfaceControl, Integer.MAX_VALUE);
         if (relative) {
-            t.reparent(mSurfaceControl, appToken.getSurfaceControl());
+            t.reparent(mSurfaceControl, mActivityRecord.getSurfaceControl());
         }
     }
 
@@ -126,12 +126,12 @@
 
     void startAnimation(Transaction t, Animation anim, Point position) {
         anim.restrictDuration(MAX_ANIMATION_DURATION);
-        anim.scaleCurrentDuration(mAppToken.mWmService.getTransitionAnimationScaleLocked());
+        anim.scaleCurrentDuration(mActivityRecord.mWmService.getTransitionAnimationScaleLocked());
         mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(
                 new WindowAnimationSpec(anim, position,
-                        mAppToken.getDisplayContent().mAppTransition.canSkipFirstFrame(),
-                        mAppToken.getDisplayContent().getWindowCornerRadius()),
-                mAppToken.mWmService.mSurfaceAnimationRunner), false /* hidden */);
+                        mActivityRecord.getDisplayContent().mAppTransition.canSkipFirstFrame(),
+                        mActivityRecord.getDisplayContent().getWindowCornerRadius()),
+                mActivityRecord.mWmService.mSurfaceAnimationRunner), false /* hidden */);
     }
 
     /**
@@ -179,19 +179,19 @@
 
     @Override
     public Transaction getPendingTransaction() {
-        return mAppToken.getPendingTransaction();
+        return mActivityRecord.getPendingTransaction();
     }
 
     @Override
     public void commitPendingTransaction() {
-        mAppToken.commitPendingTransaction();
+        mActivityRecord.commitPendingTransaction();
     }
 
     @Override
     public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
         t.setLayer(leash, Integer.MAX_VALUE);
         if (mRelative) {
-            t.reparent(leash, mAppToken.getSurfaceControl());
+            t.reparent(leash, mActivityRecord.getSurfaceControl());
         }
     }
 
@@ -205,7 +205,7 @@
 
     @Override
     public Builder makeAnimationLeash() {
-        return mAppToken.makeSurface();
+        return mActivityRecord.makeSurface();
     }
 
     @Override
@@ -215,12 +215,12 @@
 
     @Override
     public SurfaceControl getAnimationLeashParent() {
-        return mAppToken.getAppAnimationLayer();
+        return mActivityRecord.getAppAnimationLayer();
     }
 
     @Override
     public SurfaceControl getParentSurfaceControl() {
-        return mAppToken.getParentSurfaceControl();
+        return mActivityRecord.getParentSurfaceControl();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
deleted file mode 100644
index a261341..0000000
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ /dev/null
@@ -1,3446 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
-import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
-import static android.content.pm.ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
-import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
-import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
-import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
-import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
-import static android.os.Build.VERSION_CODES.HONEYCOMB;
-import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
-import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
-import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
-import static android.view.WindowManager.TRANSIT_UNSET;
-import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
-
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
-import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
-import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
-import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
-import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
-import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
-import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
-import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
-import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
-import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
-import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
-import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
-import static com.android.server.wm.AppWindowTokenProto.NAME;
-import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
-import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
-import static com.android.server.wm.AppWindowTokenProto.REMOVED;
-import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
-import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
-import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
-import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
-import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
-import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
-import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
-import static com.android.server.wm.IdentifierProto.HASH_CODE;
-import static com.android.server.wm.IdentifierProto.TITLE;
-import static com.android.server.wm.IdentifierProto.USER_ID;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
-import static com.android.server.wm.WindowManagerService.logWithStack;
-import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
-import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
-import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
-import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
-
-import android.annotation.CallSuper;
-import android.annotation.Nullable;
-import android.annotation.Size;
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.ActivityOptions;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.res.CompatibilityInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.GraphicBuffer;
-import android.graphics.PixelFormat;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.os.Binder;
-import android.os.Build;
-import android.os.Debug;
-import android.os.IBinder;
-import android.os.SystemClock;
-import android.os.Trace;
-import android.os.UserHandle;
-import android.util.ArraySet;
-import android.util.Slog;
-import android.util.proto.ProtoOutputStream;
-import android.view.DisplayInfo;
-import android.view.InputApplicationHandle;
-import android.view.RemoteAnimationAdapter;
-import android.view.RemoteAnimationDefinition;
-import android.view.SurfaceControl;
-import android.view.SurfaceControl.Transaction;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
-import android.view.animation.Animation;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ToBooleanFunction;
-import com.android.server.AttributeCache;
-import com.android.server.LocalServices;
-import com.android.server.display.color.ColorDisplayService;
-import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.policy.WindowManagerPolicy.StartingSurface;
-import com.android.server.protolog.common.ProtoLog;
-import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
-import com.android.server.wm.WindowManagerService.H;
-
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.function.Consumer;
-
-class AppTokenList extends ArrayList<AppWindowToken> {
-}
-
-/**
- * Version of WindowToken that is specifically for a particular application (or
- * really activity) that is displaying windows.
- */
-// TODO: Fully merge this class into ActivityRecord class since they are really the same thing...
-class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener {
-    private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
-
-    /**
-     * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
-     */
-    @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
-
-    final ActivityTaskManagerService mAtmService;
-    // Non-null only for application tokens.
-    // TODO: rename to mActivityToken
-    final ActivityRecord.Token appToken;
-    // All about me
-    final ActivityInfo mActivityInfo;
-    // Which user is this running for?
-    final int mUserId;
-    // The package implementing intent's component
-    // TODO: rename to mPackageName
-    final String packageName;
-    // the intent component, or target of an alias.
-    final ComponentName mActivityComponent;
-    boolean mVoiceInteraction;
-
-    /**
-     * The activity is opaque and fills the entire space of this task.
-     * @see WindowContainer#fillsParent()
-     */
-    private boolean mOccludesParent;
-    // Has a wallpaper window as a background.
-    // TODO: Rename to mHasWallpaper and also see if it possible to combine this with the
-    // mOccludesParent field.
-    final boolean hasWallpaper;
-    // activity is not displayed?
-    // TODO: rename to mNoDisplay
-    @VisibleForTesting
-    boolean noDisplay;
-    boolean mShowForAllUsers;
-    // TODO: Make this final
-    int mTargetSdk;
-
-    // Flag set while reparenting to prevent actions normally triggered by an individual parent
-    // change.
-    private boolean mReparenting;
-
-    // True if we are current in the process of removing this app token from the display
-    private boolean mRemovingFromDisplay = false;
-
-    // The input dispatching timeout for this application token in nanoseconds.
-    long mInputDispatchingTimeoutNanos;
-
-    // These are used for determining when all windows associated with
-    // an activity have been drawn, so they can be made visible together
-    // at the same time.
-    // initialize so that it doesn't match mTransactionSequence which is an int.
-    private long mLastTransactionSequence = Long.MIN_VALUE;
-    private int mNumInterestingWindows;
-    private int mNumDrawnWindows;
-    boolean inPendingTransaction;
-    boolean allDrawn;
-    private boolean mLastAllDrawn;
-    private boolean mUseTransferredAnimation;
-
-    // Set to true when this app creates a surface while in the middle of an animation. In that
-    // case do not clear allDrawn until the animation completes.
-    boolean deferClearAllDrawn;
-
-    // Is this window's surface needed?  This is almost like hidden, except
-    // it will sometimes be true a little earlier: when the token has
-    // been shown, but is still waiting for its app transition to execute
-    // before making its windows shown.
-    boolean hiddenRequested;
-
-    // Have we told the window clients to hide themselves?
-    private boolean mClientHidden;
-
-    // If true we will defer setting mClientHidden to true and reporting to the client that it is
-    // hidden.
-    boolean mDeferHidingClient;
-
-    // Last visibility state we reported to the app token.
-    boolean reportedVisible;
-
-    // Last drawn state we reported to the app token.
-    private boolean reportedDrawn;
-
-    // Set to true when the token has been removed from the window mgr.
-    boolean removed;
-
-    // Information about an application starting window if displayed.
-    // Note: these are de-referenced before the starting window animates away.
-    StartingData mStartingData;
-    WindowState startingWindow;
-    StartingSurface startingSurface;
-    boolean startingDisplayed;
-    boolean startingMoved;
-
-    // True if the hidden state of this token was forced to false due to a transferred starting
-    // window.
-    private boolean mHiddenSetFromTransferredStartingWindow;
-    boolean firstWindowDrawn;
-    private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
-            new WindowState.UpdateReportedVisibilityResults();
-
-    // Input application handle used by the input dispatcher.
-    final InputApplicationHandle mInputApplicationHandle;
-
-    // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
-    boolean mIsExiting;
-
-    boolean mLaunchTaskBehind;
-    boolean mEnteringAnimation;
-
-    boolean mAppStopped;
-    // A hint to override the window specified rotation animation, or -1 to use the window specified
-    // value. We use this so that we can select the right animation in the cases of starting
-    // windows, where the app hasn't had time to set a value on the window.
-    int mRotationAnimationHint = -1;
-
-    private int mPendingRelaunchCount;
-
-    private boolean mLastContainsShowWhenLockedWindow;
-    private boolean mLastContainsDismissKeyguardWindow;
-
-    ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
-    ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
-
-    /**
-     * The scale to fit at least one side of the activity to its parent. If the activity uses
-     * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
-     */
-    private float mSizeCompatScale = 1f;
-    /**
-     * The bounds in global coordinates for activity in size compatibility mode.
-     * @see ActivityRecord#inSizeCompatMode
-     */
-    private Rect mSizeCompatBounds;
-
-    private boolean mDisablePreviewScreenshots;
-
-    private Task mLastParent;
-
-    /**
-     * @see #currentLaunchCanTurnScreenOn()
-     */
-    private boolean mCurrentLaunchCanTurnScreenOn = true;
-
-    /**
-     * If we are running an animation, this determines the transition type. Must be one of
-     * AppTransition.TRANSIT_* constants.
-     */
-    private int mTransit;
-
-    /**
-     * If we are running an animation, this determines the flags during this animation. Must be a
-     * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
-     */
-    private int mTransitFlags;
-
-    /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
-    private boolean mLastSurfaceShowing = true;
-
-    /**
-     * This gets used during some open/close transitions as well as during a change transition
-     * where it represents the starting-state snapshot.
-     */
-    private AppWindowThumbnail mThumbnail;
-    private final Rect mTransitStartRect = new Rect();
-
-    /**
-     * This leash is used to "freeze" the app surface in place after the state change, but before
-     * the animation is ready to start.
-     */
-    private SurfaceControl mTransitChangeLeash = null;
-
-    /** Have we been asked to have this token keep the screen frozen? */
-    private boolean mFreezingScreen;
-
-    /** Whether this token should be boosted at the top of all app window tokens. */
-    @VisibleForTesting boolean mNeedsZBoost;
-    private Letterbox mLetterbox;
-
-    private final Point mTmpPoint = new Point();
-    private final Rect mTmpRect = new Rect();
-    private final Rect mTmpPrevBounds = new Rect();
-    private RemoteAnimationDefinition mRemoteAnimationDefinition;
-    private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
-
-    /**
-     * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
-     * to help AWT know that the app is in the process of closing but hasn't yet started closing on
-     * the WM side.
-     */
-    private boolean mWillCloseOrEnterPip;
-
-    /** Layer used to constrain the animation to a token's stack bounds. */
-    SurfaceControl mAnimationBoundsLayer;
-
-    /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
-    boolean mNeedsAnimationBoundsLayer;
-
-    private static final int STARTING_WINDOW_TYPE_NONE = 0;
-    private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
-    private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
-
-    private boolean mShowWhenLocked;
-    private boolean mInheritShownWhenLocked;
-    private boolean mTurnScreenOn;
-
-    private AppSaturationInfo mLastAppSaturationInfo;
-
-    private final ColorDisplayService.ColorTransformController mColorTransformController =
-            (matrix, translation) -> mWmService.mH.post(() -> {
-                synchronized (mWmService.mGlobalLock) {
-                    if (mLastAppSaturationInfo == null) {
-                        mLastAppSaturationInfo = new AppSaturationInfo();
-                    }
-
-                    mLastAppSaturationInfo.setSaturation(matrix, translation);
-                    updateColorTransform();
-                }
-            });
-
-    AppWindowToken(WindowManagerService service, ActivityTaskManagerService atm,
-            ActivityRecord.Token token, ActivityInfo aInfo, ActivityOptions options, Intent intent,
-            DisplayContent dc) {
-        super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
-                false /* ownerCanManageAppTokens */);
-        mAtmService = atm;
-        appToken = token;
-        mActivityInfo = aInfo;
-        mUserId = UserHandle.getUserId(mActivityInfo.applicationInfo.uid);
-        packageName = mActivityInfo.applicationInfo.packageName;
-        mInputApplicationHandle = new InputApplicationHandle(appToken);
-
-        // If the class name in the intent doesn't match that of the target, this is probably an
-        // alias. We have to create a new ComponentName object to keep track of the real activity
-        // name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
-        if (mActivityInfo.targetActivity == null
-                || (mActivityInfo.targetActivity.equals(intent.getComponent().getClassName())
-                && (mActivityInfo.launchMode == LAUNCH_MULTIPLE
-                || mActivityInfo.launchMode == LAUNCH_SINGLE_TOP))) {
-            mActivityComponent = intent.getComponent();
-        } else {
-            mActivityComponent =
-                    new ComponentName(mActivityInfo.packageName, mActivityInfo.targetActivity);
-        }
-
-        mTargetSdk = mActivityInfo.applicationInfo.targetSdkVersion;
-        mShowForAllUsers = (mActivityInfo.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
-        setOrientation(mActivityInfo.screenOrientation);
-        mRotationAnimationHint = mActivityInfo.rotationAnimation;
-
-        mShowWhenLocked = (aInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0;
-        mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
-        mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
-
-        int realTheme = mActivityInfo.getThemeResource();
-        if (realTheme == Resources.ID_NULL) {
-            realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
-                    ? android.R.style.Theme : android.R.style.Theme_Holo;
-        }
-
-        final AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
-                realTheme, com.android.internal.R.styleable.Window, mUserId);
-
-        if (ent != null) {
-            mOccludesParent = !ActivityInfo.isTranslucentOrFloating(ent.array);
-            hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
-            noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
-        } else {
-            hasWallpaper = false;
-            noDisplay = false;
-        }
-
-        if (options != null) {
-            mLaunchTaskBehind = options.getLaunchTaskBehind();
-
-            final int rotationAnimation = options.getRotationAnimationHint();
-            // Only override manifest supplied option if set.
-            if (rotationAnimation >= 0) {
-                mRotationAnimationHint = rotationAnimation;
-            }
-        }
-
-        // Application tokens start out hidden.
-        setHidden(true);
-        hiddenRequested = true;
-
-        ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
-                ColorDisplayService.ColorDisplayServiceInternal.class);
-        cds.attachColorTransformController(packageName, mUserId,
-                new WeakReference<>(mColorTransformController));
-    }
-
-    void onAttachToTask(boolean voiceInteraction, DisplayContent dc,
-            long inputDispatchingTimeoutNanos) {
-        mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
-        mVoiceInteraction = voiceInteraction;
-        onDisplayChanged(dc);
-
-        // Application tokens start out hidden.
-        setHidden(true);
-        hiddenRequested = true;
-    }
-
-    void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
-        firstWindowDrawn = true;
-
-        // We now have a good window to show, remove dead placeholders
-        removeDeadWindows();
-
-        if (startingWindow != null) {
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finish starting %s"
-                        + ": first real window is shown, no animation", win.mToken);
-            // If this initial window is animating, stop it -- we will do an animation to reveal
-            // it from behind the starting window, so there is no need for it to also be doing its
-            // own stuff.
-            win.cancelAnimation();
-        }
-        removeStartingWindow();
-        updateReportedVisibilityLocked();
-    }
-
-    void updateReportedVisibilityLocked() {
-        if (appToken == null) {
-            return;
-        }
-
-        if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
-        final int count = mChildren.size();
-
-        mReportedVisibilityResults.reset();
-
-        for (int i = 0; i < count; i++) {
-            final WindowState win = mChildren.get(i);
-            win.updateReportedVisibility(mReportedVisibilityResults);
-        }
-
-        int numInteresting = mReportedVisibilityResults.numInteresting;
-        int numVisible = mReportedVisibilityResults.numVisible;
-        int numDrawn = mReportedVisibilityResults.numDrawn;
-        boolean nowGone = mReportedVisibilityResults.nowGone;
-
-        boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
-        boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
-        if (!nowGone) {
-            // If the app is not yet gone, then it can only become visible/drawn.
-            if (!nowDrawn) {
-                nowDrawn = reportedDrawn;
-            }
-            if (!nowVisible) {
-                nowVisible = reportedVisible;
-            }
-        }
-        if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
-                + numInteresting + " visible=" + numVisible);
-        if (nowDrawn != reportedDrawn) {
-            onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
-            reportedDrawn = nowDrawn;
-        }
-        if (nowVisible != reportedVisible) {
-            if (DEBUG_VISIBILITY) Slog.v(TAG,
-                    "Visibility changed in " + this + ": vis=" + nowVisible);
-            reportedVisible = nowVisible;
-            if (nowVisible) {
-                onWindowsVisible();
-            } else {
-                onWindowsGone();
-            }
-        }
-    }
-
-    // Mostly implemented in ActivityRecord.
-    void onWindowsDrawn(boolean drawn, long timestamp) {
-    }
-
-    // Mostly implemented in ActivityRecord. Keeping here for the logpoint.
-    void onWindowsGone() {
-        if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in " + appToken);
-    }
-
-    // Mostly implemented in ActivityRecord. Keeping here for the logpoint.
-    void onWindowsVisible() {
-        if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in " + appToken);
-    }
-
-    boolean isClientHidden() {
-        return mClientHidden;
-    }
-
-    void setClientHidden(boolean hideClient) {
-        if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
-            return;
-        }
-        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                "setClientHidden: %s clientHidden=%b Callers=%s", this, hideClient,
-                        Debug.getCallers(5));
-        mClientHidden = hideClient;
-        sendAppVisibilityToClients();
-    }
-
-    void setVisibility(boolean visible, boolean deferHidingClient) {
-        final AppTransition appTransition = getDisplayContent().mAppTransition;
-
-        // Don't set visibility to false if we were already not visible. This prevents WM from
-        // adding the app to the closing app list which doesn't make sense for something that is
-        // already not visible. However, set visibility to true even if we are already visible.
-        // This makes sure the app is added to the opening apps list so that the right
-        // transition can be selected.
-        // TODO: Probably a good idea to separate the concept of opening/closing apps from the
-        // concept of setting visibility...
-        if (!visible && hiddenRequested) {
-
-            if (!deferHidingClient && mDeferHidingClient) {
-                // We previously deferred telling the client to hide itself when visibility was
-                // initially set to false. Now we would like it to hide, so go ahead and set it.
-                mDeferHidingClient = deferHidingClient;
-                setClientHidden(true);
-            }
-            return;
-        }
-
-        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                    "setAppVisibility(%s, visible=%b): %s hidden=%b hiddenRequested=%b Callers=%s",
-                    appToken, visible, appTransition, isHidden(), hiddenRequested,
-                    Debug.getCallers(6));
-
-        final DisplayContent displayContent = getDisplayContent();
-        displayContent.mOpeningApps.remove(this);
-        displayContent.mClosingApps.remove(this);
-        if (isInChangeTransition()) {
-            clearChangeLeash(getPendingTransaction(), true /* cancel */);
-        }
-        displayContent.mChangingApps.remove(this);
-        waitingToShow = false;
-        hiddenRequested = !visible;
-        mDeferHidingClient = deferHidingClient;
-
-        if (!visible) {
-            // If the app is dead while it was visible, we kept its dead window on screen.
-            // Now that the app is going invisible, we can remove it. It will be restarted
-            // if made visible again.
-            removeDeadWindows();
-        } else {
-            if (!appTransition.isTransitionSet()
-                    && appTransition.isReady()) {
-                // Add the app mOpeningApps if transition is unset but ready. This means
-                // we're doing a screen freeze, and the unfreeze will wait for all opening
-                // apps to be ready.
-                displayContent.mOpeningApps.add(this);
-            }
-            startingMoved = false;
-            // If the token is currently hidden (should be the common case), or has been
-            // stopped, then we need to set up to wait for its windows to be ready.
-            if (isHidden() || mAppStopped) {
-                clearAllDrawn();
-
-                // If the app was already visible, don't reset the waitingToShow state.
-                if (isHidden()) {
-                    waitingToShow = true;
-
-                    // If the client isn't hidden, we don't need to reset the drawing state.
-                    if (isClientHidden()) {
-                        // Let's reset the draw state in order to prevent the starting window to be
-                        // immediately dismissed when the app still has the surface.
-                        forAllWindows(w -> {
-                            if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
-                                w.mWinAnimator.resetDrawState();
-
-                                // Force add to mResizingWindows, so that we are guaranteed to get
-                                // another reportDrawn callback.
-                                w.resetLastContentInsets();
-                            }
-                        }, true /* traverseTopToBottom */);
-                    }
-                }
-            }
-
-            // In the case where we are making an app visible but holding off for a transition,
-            // we still need to tell the client to make its windows visible so they get drawn.
-            // Otherwise, we will wait on performing the transition until all windows have been
-            // drawn, they never will be, and we are sad.
-            setClientHidden(false);
-
-            requestUpdateWallpaperIfNeeded();
-
-            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "No longer Stopped: %s", this);
-            mAppStopped = false;
-
-            transferStartingWindowFromHiddenAboveTokenIfNeeded();
-        }
-
-        // If we are preparing an app transition, then delay changing
-        // the visibility of this token until we execute that transition.
-        if (okToAnimate() && appTransition.isTransitionSet()) {
-            inPendingTransaction = true;
-            if (visible) {
-                displayContent.mOpeningApps.add(this);
-                mEnteringAnimation = true;
-            } else {
-                displayContent.mClosingApps.add(this);
-                mEnteringAnimation = false;
-            }
-            if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
-                // We're launchingBehind, add the launching activity to mOpeningApps.
-                final WindowState win = getDisplayContent().findFocusedWindow();
-                if (win != null) {
-                    final AppWindowToken focusedToken = win.mAppToken;
-                    if (focusedToken != null) {
-                        ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
-                                    "TRANSIT_TASK_OPEN_BEHIND,  adding %s to mOpeningApps",
-                                    focusedToken);
-
-                        // Force animation to be loaded.
-                        displayContent.mOpeningApps.add(focusedToken);
-                    }
-                }
-            }
-            return;
-        }
-
-        commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
-        updateReportedVisibilityLocked();
-    }
-
-    boolean commitVisibility(WindowManager.LayoutParams lp,
-            boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
-
-        boolean delayed = false;
-        inPendingTransaction = false;
-        // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
-        // been set by the app now.
-        mHiddenSetFromTransferredStartingWindow = false;
-
-        // Allow for state changes and animation to be applied if:
-        // * token is transitioning visibility state
-        // * or the token was marked as hidden and is exiting before we had a chance to play the
-        // transition animation
-        // * or this is an opening app and windows are being replaced
-        // * or the token is the opening app and visible while opening task behind existing one.
-        final DisplayContent displayContent = getDisplayContent();
-        boolean visibilityChanged = false;
-        if (isHidden() == visible || (isHidden() && mIsExiting)
-                || (visible && waitingForReplacement())
-                || (visible && displayContent.mOpeningApps.contains(this)
-                && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) {
-            final AccessibilityController accessibilityController =
-                    mWmService.mAccessibilityController;
-            boolean changed = false;
-            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                    "Changing app %s hidden=%b performLayout=%b", this, isHidden(),
-                            performLayout);
-
-            boolean runningAppAnimation = false;
-
-            if (transit != WindowManager.TRANSIT_UNSET) {
-                if (mUseTransferredAnimation) {
-                    runningAppAnimation = isReallyAnimating();
-                } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
-                    runningAppAnimation = true;
-                }
-                delayed = runningAppAnimation;
-                final WindowState window = findMainWindow();
-                if (window != null && accessibilityController != null) {
-                    accessibilityController.onAppWindowTransitionLocked(window, transit);
-                }
-                changed = true;
-            }
-
-            final int windowsCount = mChildren.size();
-            for (int i = 0; i < windowsCount; i++) {
-                final WindowState win = mChildren.get(i);
-                changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
-            }
-
-            setHidden(!visible);
-            hiddenRequested = !visible;
-            visibilityChanged = true;
-            if (!visible) {
-                stopFreezingScreen(true, true);
-            } else {
-                // If we are being set visible, and the starting window is not yet displayed,
-                // then make sure it doesn't get displayed.
-                if (startingWindow != null && !startingWindow.isDrawnLw()) {
-                    startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
-                    startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
-                }
-
-                // We are becoming visible, so better freeze the screen with the windows that are
-                // getting visible so we also wait for them.
-                forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
-            }
-
-            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                        "commitVisibility: %s: hidden=%b hiddenRequested=%b", this,
-                                isHidden(), hiddenRequested);
-
-            if (changed) {
-                displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
-                if (performLayout) {
-                    mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-                            false /*updateInputWindows*/);
-                    mWmService.mWindowPlacerLocked.performSurfacePlacement();
-                }
-                displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
-            }
-        }
-        mUseTransferredAnimation = false;
-
-        if (isReallyAnimating()) {
-            delayed = true;
-        } else {
-
-            // We aren't animating anything, but exiting windows rely on the animation finished
-            // callback being called in case the AppWindowToken was pretending to be animating,
-            // which we might have done because we were in closing/opening apps list.
-            onAnimationFinished();
-        }
-
-        for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
-            if ((mChildren.get(i)).isSelfOrChildAnimating()) {
-                delayed = true;
-            }
-        }
-
-        if (visibilityChanged) {
-            if (visible && !delayed) {
-                // The token was made immediately visible, there will be no entrance animation.
-                // We need to inform the client the enter animation was finished.
-                mEnteringAnimation = true;
-                mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
-                        token);
-            }
-
-            // If we're becoming visible, immediately change client visibility as well. there seem
-            // to be some edge cases where we change our visibility but client visibility never gets
-            // updated.
-            // If we're becoming invisible, update the client visibility if we are not running an
-            // animation. Otherwise, we'll update client visibility in onAnimationFinished.
-            if (visible || !isReallyAnimating()) {
-                setClientHidden(!visible);
-            }
-
-            if (!displayContent.mClosingApps.contains(this)
-                    && !displayContent.mOpeningApps.contains(this)) {
-                // The token is not closing nor opening, so even if there is an animation set, that
-                // doesn't mean that it goes through the normal app transition cycle so we have
-                // to inform the docked controller about visibility change.
-                // TODO(multi-display): notify docked divider on all displays where visibility was
-                // affected.
-                displayContent.getDockedDividerController().notifyAppVisibilityChanged();
-
-                // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
-                // will not be taken.
-                mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
-            }
-
-            // If we are hidden but there is no delay needed we immediately
-            // apply the Surface transaction so that the ActivityManager
-            // can have some guarantee on the Surface state following
-            // setting the visibility. This captures cases like dismissing
-            // the docked or pinned stack where there is no app transition.
-            //
-            // In the case of a "Null" animation, there will be
-            // no animation but there will still be a transition set.
-            // We still need to delay hiding the surface such that it
-            // can be synchronized with showing the next surface in the transition.
-            if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
-                SurfaceControl.openTransaction();
-                for (int i = mChildren.size() - 1; i >= 0; i--) {
-                    mChildren.get(i).mWinAnimator.hide("immediately hidden");
-                }
-                SurfaceControl.closeTransaction();
-            }
-        }
-
-        return delayed;
-    }
-
-    boolean mayFreezeScreenLocked() {
-        return false;
-    }
-
-    void reportDescendantOrientationChangeIfNeeded() {
-        // Orientation request is exposed only when we're visible. Therefore visibility change
-        // will change requested orientation. Notify upward the hierarchy ladder to adjust
-        // configuration. This is important to cases where activities with incompatible
-        // orientations launch, or user goes back from an activity of bi-orientation to an
-        // activity with specified orientation.
-        if (getRequestedOrientation() == SCREEN_ORIENTATION_UNSET) {
-            return;
-        }
-
-        final IBinder freezeToken = mayFreezeScreenLocked() ? appToken : null;
-        onDescendantOrientationChanged(freezeToken, this);
-    }
-
-    /**
-     * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
-     *         true.
-     */
-    WindowState getTopFullscreenWindow() {
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState win = mChildren.get(i);
-            if (win != null && win.mAttrs.isFullscreen()) {
-                return win;
-            }
-        }
-        return null;
-    }
-
-    WindowState findMainWindow() {
-        return findMainWindow(true);
-    }
-
-    /**
-     * Finds the main window that either has type base application or application starting if
-     * requested.
-     *
-     * @param includeStartingApp Allow to search application-starting windows to also be returned.
-     * @return The main window of type base application or application starting if requested.
-     */
-    WindowState findMainWindow(boolean includeStartingApp) {
-        WindowState candidate = null;
-        for (int j = mChildren.size() - 1; j >= 0; --j) {
-            final WindowState win = mChildren.get(j);
-            final int type = win.mAttrs.type;
-            // No need to loop through child window as base application and starting types can't be
-            // child windows.
-            if (type == TYPE_BASE_APPLICATION
-                    || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
-                // In cases where there are multiple windows, we prefer the non-exiting window. This
-                // happens for example when replacing windows during an activity relaunch. When
-                // constructing the animation, we want the new window, not the exiting one.
-                if (win.mAnimatingExit) {
-                    candidate = win;
-                } else {
-                    return win;
-                }
-            }
-        }
-        return candidate;
-    }
-
-    boolean isAlwaysFocusable() {
-        return (mActivityInfo.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
-    }
-
-    // TODO: Does this really need to be different from isAlwaysFocusable()? For the activity side
-    // focusable means resumeable. I guess with that in mind maybe we should rename the other
-    // method to isResumeable() or something like that.
-    boolean windowsAreFocusable() {
-        if (mTargetSdk < Build.VERSION_CODES.Q) {
-            final int pid = getPid();
-            final AppWindowToken topFocusedAppOfMyProcess =
-                    mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
-            if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
-                // For the apps below Q, there can be only one app which has the focused window per
-                // process, because legacy apps may not be ready for a multi-focus system.
-                return false;
-            }
-        }
-        return getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable();
-    }
-
-    // Mostly implemented in ActivityRecord...
-    int getPid() {
-        return 0;
-    }
-
-    @Override
-    boolean isVisible() {
-        // If the app token isn't hidden then it is considered visible and there is no need to check
-        // its children windows to see if they are visible.
-        return !isHidden();
-    }
-
-    @Override
-    void removeImmediately() {
-        onRemovedFromDisplay();
-        super.removeImmediately();
-    }
-
-    @Override
-    void removeIfPossible() {
-        mIsExiting = false;
-        removeAllWindowsIfPossible();
-        removeImmediately();
-    }
-
-    @Override
-    boolean checkCompleteDeferredRemoval() {
-        if (mIsExiting) {
-            removeIfPossible();
-        }
-        return super.checkCompleteDeferredRemoval();
-    }
-
-    void onRemovedFromDisplay() {
-        if (mRemovingFromDisplay) {
-            return;
-        }
-        mRemovingFromDisplay = true;
-
-        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this);
-
-        boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
-
-        getDisplayContent().mOpeningApps.remove(this);
-        getDisplayContent().mChangingApps.remove(this);
-        getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
-        mWmService.mTaskSnapshotController.onAppRemoved(this);
-        waitingToShow = false;
-        if (getDisplayContent().mClosingApps.contains(this)) {
-            delayed = true;
-        } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
-            getDisplayContent().mClosingApps.add(this);
-            delayed = true;
-        }
-
-        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                "Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
-                        getAnimation(), isSelfAnimating());
-
-        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
-                + " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
-
-        if (mStartingData != null) {
-            removeStartingWindow();
-        }
-
-        // If this window was animating, then we need to ensure that the app transition notifies
-        // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
-        // so add to that list now
-        if (isSelfAnimating()) {
-            getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
-        }
-
-        final TaskStack stack = getStack();
-        if (delayed && !isEmpty()) {
-            // set the token aside because it has an active animation to be finished
-            ProtoLog.v(WM_DEBUG_ADD_REMOVE,
-                    "removeAppToken make exiting: %s", this);
-            if (stack != null) {
-                stack.mExitingAppTokens.add(this);
-            }
-            mIsExiting = true;
-        } else {
-            // Make sure there is no animation running on this token, so any windows associated
-            // with it will be removed as soon as their animations are complete
-            cancelAnimation();
-            if (stack != null) {
-                stack.mExitingAppTokens.remove(this);
-            }
-            removeIfPossible();
-        }
-
-        removed = true;
-        stopFreezingScreen(true, true);
-
-        final DisplayContent dc = getDisplayContent();
-        if (dc.mFocusedApp == this) {
-            ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
-                    "Removing focused app token:%s displayId=%d", this,
-                            dc.getDisplayId());
-            dc.setFocusedApp(null);
-            mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
-        }
-        if (mLetterbox != null) {
-            mLetterbox.destroy();
-            mLetterbox = null;
-        }
-
-        if (!delayed) {
-            updateReportedVisibilityLocked();
-        }
-
-        // Reset the last saved PiP snap fraction on removal.
-        mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
-
-        mRemovingFromDisplay = false;
-    }
-
-    void clearAnimatingFlags() {
-        boolean wallpaperMightChange = false;
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState win = mChildren.get(i);
-            wallpaperMightChange |= win.clearAnimatingFlags();
-        }
-        if (wallpaperMightChange) {
-            requestUpdateWallpaperIfNeeded();
-        }
-    }
-
-    void destroySurfaces() {
-        destroySurfaces(false /*cleanupOnResume*/);
-    }
-
-    /**
-     * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
-     * the client has finished with them.
-     *
-     * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
-     * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
-     * others so that they are ready to be reused. If set to false (common case), destroy all
-     * surfaces that's eligible, if the app is already stopped.
-     */
-    private void destroySurfaces(boolean cleanupOnResume) {
-        boolean destroyedSomething = false;
-
-        // Copying to a different list as multiple children can be removed.
-        final ArrayList<WindowState> children = new ArrayList<>(mChildren);
-        for (int i = children.size() - 1; i >= 0; i--) {
-            final WindowState win = children.get(i);
-            destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
-        }
-        if (destroyedSomething) {
-            final DisplayContent dc = getDisplayContent();
-            dc.assignWindowLayers(true /*setLayoutNeeded*/);
-            updateLetterboxSurface(null);
-        }
-    }
-
-    /**
-     * Notify that the app is now resumed, and it was not stopped before, perform a clean
-     * up of the surfaces
-     */
-    void notifyAppResumed(boolean wasStopped) {
-        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppResumed: wasStopped=%b %s",
-                wasStopped, this);
-        mAppStopped = false;
-        // Allow the window to turn the screen on once the app is resumed again.
-        setCurrentLaunchCanTurnScreenOn(true);
-        if (!wasStopped) {
-            destroySurfaces(true /*cleanupOnResume*/);
-        }
-    }
-
-    /**
-     * Notify that the app has stopped, and it is okay to destroy any surfaces which were
-     * keeping alive in case they were still being used.
-     */
-    void notifyAppStopped() {
-        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
-        mAppStopped = true;
-        // Reset the last saved PiP snap fraction on app stop.
-        mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
-        destroySurfaces();
-        // Remove any starting window that was added for this app if they are still around.
-        removeStartingWindow();
-    }
-
-    void clearAllDrawn() {
-        allDrawn = false;
-        deferClearAllDrawn = false;
-    }
-
-    Task getTask() {
-        return (Task) getParent();
-    }
-
-    TaskStack getStack() {
-        final Task task = getTask();
-        if (task != null) {
-            return task.mStack;
-        } else {
-            return null;
-        }
-    }
-
-    @Override
-    void onParentChanged() {
-        super.onParentChanged();
-
-        final Task task = getTask();
-
-        // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
-        // access visual elements like the {@link DisplayContent}. We must remove any associations
-        // such as animations.
-        if (!mReparenting) {
-            if (task == null) {
-                // It is possible we have been marked as a closing app earlier. We must remove ourselves
-                // from this list so we do not participate in any future animations.
-                if (getDisplayContent() != null) {
-                    getDisplayContent().mClosingApps.remove(this);
-                }
-            } else if (mLastParent != null && mLastParent.mStack != null) {
-                task.mStack.mExitingAppTokens.remove(this);
-            }
-        }
-        final TaskStack stack = getStack();
-
-        // If we reparent, make sure to remove ourselves from the old animation registry.
-        if (mAnimatingAppWindowTokenRegistry != null) {
-            mAnimatingAppWindowTokenRegistry.notifyFinished(this);
-        }
-        mAnimatingAppWindowTokenRegistry = stack != null
-                ? stack.getAnimatingAppWindowTokenRegistry()
-                : null;
-
-        mLastParent = task;
-
-        updateColorTransform();
-    }
-
-    void postWindowRemoveStartingWindowCleanup(WindowState win) {
-        // TODO: Something smells about the code below...Is there a better way?
-        if (startingWindow == win) {
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Notify removed startingWindow %s", win);
-            removeStartingWindow();
-        } else if (mChildren.size() == 0) {
-            // If this is the last window and we had requested a starting transition window,
-            // well there is no point now.
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData");
-            mStartingData = null;
-            if (mHiddenSetFromTransferredStartingWindow) {
-                // We set the hidden state to false for the token from a transferred starting window.
-                // We now reset it back to true since the starting window was the last window in the
-                // token.
-                setHidden(true);
-            }
-        } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
-            // If this is the last window except for a starting transition window,
-            // we need to get rid of the starting transition.
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Last window, removing starting window %s", win);
-            removeStartingWindow();
-        }
-    }
-
-    void removeDeadWindows() {
-        for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
-            WindowState win = mChildren.get(winNdx);
-            if (win.mAppDied) {
-                ProtoLog.w(WM_DEBUG_ADD_REMOVE,
-                        "removeDeadWindows: %s", win);
-                // Set mDestroying, we don't want any animation or delayed removal here.
-                win.mDestroying = true;
-                // Also removes child windows.
-                win.removeIfPossible();
-            }
-        }
-    }
-
-    boolean hasWindowsAlive() {
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            // No need to loop through child windows as the answer should be the same as that of the
-            // parent window.
-            if (!(mChildren.get(i)).mAppDied) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    void setWillReplaceWindows(boolean animate) {
-        ProtoLog.d(WM_DEBUG_ADD_REMOVE,
-                "Marking app token %s with replacing windows.", this);
-
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState w = mChildren.get(i);
-            w.setWillReplaceWindow(animate);
-        }
-    }
-
-    void setWillReplaceChildWindows() {
-        ProtoLog.d(WM_DEBUG_ADD_REMOVE, "Marking app token %s"
-                + " with replacing child windows.", this);
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState w = mChildren.get(i);
-            w.setWillReplaceChildWindows();
-        }
-    }
-
-    void clearWillReplaceWindows() {
-        ProtoLog.d(WM_DEBUG_ADD_REMOVE,
-                "Resetting app token %s of replacing window marks.", this);
-
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState w = mChildren.get(i);
-            w.clearWillReplaceWindow();
-        }
-    }
-
-    void requestUpdateWallpaperIfNeeded() {
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState w = mChildren.get(i);
-            w.requestUpdateWallpaperIfNeeded();
-        }
-    }
-
-    boolean isRelaunching() {
-        return mPendingRelaunchCount > 0;
-    }
-
-    boolean shouldFreezeBounds() {
-        final Task task = getTask();
-
-        // For freeform windows, we can't freeze the bounds at the moment because this would make
-        // the resizing unresponsive.
-        if (task == null || task.inFreeformWindowingMode()) {
-            return false;
-        }
-
-        // We freeze the bounds while drag resizing to deal with the time between
-        // the divider/drag handle being released, and the handling it's new
-        // configuration. If we are relaunched outside of the drag resizing state,
-        // we need to be careful not to do this.
-        return getTask().isDragResizing();
-    }
-
-    void startRelaunching() {
-        if (shouldFreezeBounds()) {
-            freezeBounds();
-        }
-
-        // In the process of tearing down before relaunching, the app will
-        // try and clean up it's child surfaces. We need to prevent this from
-        // happening, so we sever the children, transfering their ownership
-        // from the client it-self to the parent surface (owned by us).
-        detachChildren();
-
-        mPendingRelaunchCount++;
-    }
-
-    void detachChildren() {
-        SurfaceControl.openTransaction();
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState w = mChildren.get(i);
-            w.mWinAnimator.detachChildren();
-        }
-        SurfaceControl.closeTransaction();
-    }
-
-    void finishRelaunching() {
-        unfreezeBounds();
-
-        if (mPendingRelaunchCount > 0) {
-            mPendingRelaunchCount--;
-        } else {
-            // Update keyguard flags upon finishing relaunch.
-            checkKeyguardFlagsChanged();
-        }
-    }
-
-    void clearRelaunching() {
-        if (mPendingRelaunchCount == 0) {
-            return;
-        }
-        unfreezeBounds();
-        mPendingRelaunchCount = 0;
-    }
-
-    /**
-     * Returns true if the new child window we are adding to this token is considered greater than
-     * the existing child window in this token in terms of z-order.
-     */
-    @Override
-    protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
-            WindowState existingWindow) {
-        final int type1 = newWindow.mAttrs.type;
-        final int type2 = existingWindow.mAttrs.type;
-
-        // Base application windows should be z-ordered BELOW all other windows in the app token.
-        if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
-            return false;
-        } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
-            return true;
-        }
-
-        // Starting windows should be z-ordered ABOVE all other windows in the app token.
-        if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
-            return true;
-        } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
-            return false;
-        }
-
-        // Otherwise the new window is greater than the existing window.
-        return true;
-    }
-
-    /**
-     * @return {@code true} if starting window is in app's hierarchy.
-     */
-    boolean hasStartingWindow() {
-        if (startingDisplayed || mStartingData != null) {
-            return true;
-        }
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    void addWindow(WindowState w) {
-        super.addWindow(w);
-
-        boolean gotReplacementWindow = false;
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState candidate = mChildren.get(i);
-            gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
-        }
-
-        // if we got a replacement window, reset the timeout to give drawing more time
-        if (gotReplacementWindow) {
-            mWmService.scheduleWindowReplacementTimeouts(this);
-        }
-        checkKeyguardFlagsChanged();
-    }
-
-    @Override
-    void removeChild(WindowState child) {
-        if (!mChildren.contains(child)) {
-            // This can be true when testing.
-            return;
-        }
-        super.removeChild(child);
-        checkKeyguardFlagsChanged();
-        updateLetterboxSurface(child);
-    }
-
-    private boolean waitingForReplacement() {
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState candidate = mChildren.get(i);
-            if (candidate.waitingForReplacement()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    void onWindowReplacementTimeout() {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            (mChildren.get(i)).onWindowReplacementTimeout();
-        }
-    }
-
-    void reparent(Task task, int position) {
-        ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving app token=%s"
-                    + " to task=%d at %d", this, task.mTaskId, position);
-
-        if (task == null) {
-            throw new IllegalArgumentException("reparent: could not find task");
-        }
-        final Task currentTask = getTask();
-        if (task == currentTask) {
-            throw new IllegalArgumentException(
-                    "window token=" + this + " already child of task=" + currentTask);
-        }
-
-        if (currentTask.mStack != task.mStack) {
-            throw new IllegalArgumentException(
-                    "window token=" + this + " current task=" + currentTask
-                        + " belongs to a different stack than " + task);
-        }
-
-        ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reParentWindowToken: removing window token=%s"
-                + " from task=%s"  , this, currentTask);
-        final DisplayContent prevDisplayContent = getDisplayContent();
-
-        mReparenting = true;
-
-        getParent().removeChild(this);
-        task.addChild(this, position);
-
-        mReparenting = false;
-
-        // Relayout display(s).
-        final DisplayContent displayContent = task.getDisplayContent();
-        displayContent.setLayoutNeeded();
-        if (prevDisplayContent != displayContent) {
-            onDisplayChanged(displayContent);
-            prevDisplayContent.setLayoutNeeded();
-        }
-        getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
-    }
-
-    @Override
-    void onDisplayChanged(DisplayContent dc) {
-        DisplayContent prevDc = mDisplayContent;
-        super.onDisplayChanged(dc);
-        if (prevDc == null || prevDc == mDisplayContent) {
-            return;
-        }
-
-        if (prevDc.mOpeningApps.remove(this)) {
-            // Transfer opening transition to new display.
-            mDisplayContent.mOpeningApps.add(this);
-            mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
-            mDisplayContent.executeAppTransition();
-        }
-
-        if (prevDc.mChangingApps.remove(this)) {
-            // This gets called *after* the AppWindowToken has been reparented to the new display.
-            // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
-            // so this token is now "frozen" while waiting for the animation to start on prevDc
-            // (which will be cancelled since the window is no-longer a child). However, since this
-            // is no longer a child of prevDc, this won't be notified of the cancelled animation,
-            // so we need to cancel the change transition here.
-            clearChangeLeash(getPendingTransaction(), true /* cancel */);
-        }
-        prevDc.mClosingApps.remove(this);
-
-        if (prevDc.mFocusedApp == this) {
-            prevDc.setFocusedApp(null);
-            final TaskStack stack = dc.getTopStack();
-            if (stack != null) {
-                final Task task = stack.getTopChild();
-                if (task != null && task.getTopChild() == this) {
-                    dc.setFocusedApp(this);
-                }
-            }
-        }
-
-        if (mLetterbox != null) {
-            mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
-        }
-    }
-
-    /**
-     * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
-     * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
-     * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
-     * with a queue.
-     */
-    private void freezeBounds() {
-        final Task task = getTask();
-        mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
-
-        if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
-            // We didn't call prepareFreezingBounds on the task, so use the current value.
-            mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
-        } else {
-            mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
-        }
-        // Calling unset() to make it equal to Configuration.EMPTY.
-        task.mPreparedFrozenMergedConfig.unset();
-    }
-
-    /**
-     * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
-     */
-    private void unfreezeBounds() {
-        if (mFrozenBounds.isEmpty()) {
-            return;
-        }
-        mFrozenBounds.remove();
-        if (!mFrozenMergedConfig.isEmpty()) {
-            mFrozenMergedConfig.remove();
-        }
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState win = mChildren.get(i);
-            win.onUnfreezeBounds();
-        }
-        mWmService.mWindowPlacerLocked.performSurfacePlacement();
-    }
-
-    void setAppLayoutChanges(int changes, String reason) {
-        if (!mChildren.isEmpty()) {
-            final DisplayContent dc = getDisplayContent();
-            dc.pendingLayoutChanges |= changes;
-            if (DEBUG_LAYOUT_REPEATS) {
-                mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
-            }
-        }
-    }
-
-    void removeReplacedWindowIfNeeded(WindowState replacement) {
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState win = mChildren.get(i);
-            if (win.removeReplacedWindowIfNeeded(replacement)) {
-                return;
-            }
-        }
-    }
-
-    void startFreezingScreen() {
-        ProtoLog.i(WM_DEBUG_ORIENTATION,
-                "Set freezing of %s: hidden=%b freezing=%b hiddenRequested=%b. %s",
-                        appToken, isHidden(), mFreezingScreen, hiddenRequested,
-                new RuntimeException().fillInStackTrace());
-        if (!hiddenRequested) {
-            if (!mFreezingScreen) {
-                mFreezingScreen = true;
-                mWmService.registerAppFreezeListener(this);
-                mWmService.mAppsFreezingScreen++;
-                if (mWmService.mAppsFreezingScreen == 1) {
-                    mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
-                    mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
-                    mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
-                }
-            }
-            final int count = mChildren.size();
-            for (int i = 0; i < count; i++) {
-                final WindowState w = mChildren.get(i);
-                w.onStartFreezingScreen();
-            }
-        }
-    }
-
-    void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
-        if (!mFreezingScreen) {
-            return;
-        }
-        ProtoLog.v(WM_DEBUG_ORIENTATION,
-                "Clear freezing of %s force=%b", this, force);
-        final int count = mChildren.size();
-        boolean unfrozeWindows = false;
-        for (int i = 0; i < count; i++) {
-            final WindowState w = mChildren.get(i);
-            unfrozeWindows |= w.onStopFreezingScreen();
-        }
-        if (force || unfrozeWindows) {
-            ProtoLog.v(WM_DEBUG_ORIENTATION, "No longer freezing: %s", this);
-            mFreezingScreen = false;
-            mWmService.unregisterAppFreezeListener(this);
-            mWmService.mAppsFreezingScreen--;
-            mWmService.mLastFinishedFreezeSource = this;
-        }
-        if (unfreezeSurfaceNow) {
-            if (unfrozeWindows) {
-                mWmService.mWindowPlacerLocked.performSurfacePlacement();
-            }
-            mWmService.stopFreezingDisplayLocked();
-        }
-    }
-
-    @Override
-    public void onAppFreezeTimeout() {
-        Slog.w(TAG_WM, "Force clearing freeze: " + this);
-        stopFreezingScreen(true, true);
-    }
-
-    /**
-     * Tries to transfer the starting window from a token that's above ourselves in the task but
-     * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
-     * activity M in the same task. Now, when reopening the task, T starts on top of M but then
-     * immediately finishes after, so we have to transfer T to M.
-     */
-    void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
-        final Task task = getTask();
-        for (int i = task.mChildren.size() - 1; i >= 0; i--) {
-            final AppWindowToken fromToken = task.mChildren.get(i);
-            if (fromToken == this) {
-                return;
-            }
-            if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
-                return;
-            }
-        }
-    }
-
-    boolean transferStartingWindow(IBinder transferFrom) {
-        final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
-        if (fromToken == null) {
-            return false;
-        }
-
-        final WindowState tStartingWindow = fromToken.startingWindow;
-        if (tStartingWindow != null && fromToken.startingSurface != null) {
-            // In this case, the starting icon has already been displayed, so start
-            // letting windows get shown immediately without any more transitions.
-            getDisplayContent().mSkipAppTransitionAnimation = true;
-
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Moving existing starting %s"
-                    + " from %s to %s", tStartingWindow, fromToken, this);
-
-            final long origId = Binder.clearCallingIdentity();
-            try {
-                // Transfer the starting window over to the new token.
-                mStartingData = fromToken.mStartingData;
-                startingSurface = fromToken.startingSurface;
-                startingDisplayed = fromToken.startingDisplayed;
-                fromToken.startingDisplayed = false;
-                startingWindow = tStartingWindow;
-                reportedVisible = fromToken.reportedVisible;
-                fromToken.mStartingData = null;
-                fromToken.startingSurface = null;
-                fromToken.startingWindow = null;
-                fromToken.startingMoved = true;
-                tStartingWindow.mToken = this;
-                tStartingWindow.mAppToken = this;
-
-                ProtoLog.v(WM_DEBUG_ADD_REMOVE,
-                        "Removing starting %s from %s", tStartingWindow, fromToken);
-                fromToken.removeChild(tStartingWindow);
-                fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
-                fromToken.mHiddenSetFromTransferredStartingWindow = false;
-                addWindow(tStartingWindow);
-
-                // Propagate other interesting state between the tokens. If the old token is displayed,
-                // we should immediately force the new one to be displayed. If it is animating, we need
-                // to move that animation to the new one.
-                if (fromToken.allDrawn) {
-                    allDrawn = true;
-                    deferClearAllDrawn = fromToken.deferClearAllDrawn;
-                }
-                if (fromToken.firstWindowDrawn) {
-                    firstWindowDrawn = true;
-                }
-                if (!fromToken.isHidden()) {
-                    setHidden(false);
-                    hiddenRequested = false;
-                    mHiddenSetFromTransferredStartingWindow = true;
-                }
-                setClientHidden(fromToken.mClientHidden);
-
-                transferAnimation(fromToken);
-
-                // When transferring an animation, we no longer need to apply an animation to the
-                // the token we transfer the animation over. Thus, set this flag to indicate we've
-                // transferred the animation.
-                mUseTransferredAnimation = true;
-
-                mWmService.updateFocusedWindowLocked(
-                        UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
-                getDisplayContent().setLayoutNeeded();
-                mWmService.mWindowPlacerLocked.performSurfacePlacement();
-            } finally {
-                Binder.restoreCallingIdentity(origId);
-            }
-            return true;
-        } else if (fromToken.mStartingData != null) {
-            // The previous app was getting ready to show a
-            // starting window, but hasn't yet done so.  Steal it!
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
-                    "Moving pending starting from %s to %s", fromToken, this);
-            mStartingData = fromToken.mStartingData;
-            fromToken.mStartingData = null;
-            fromToken.startingMoved = true;
-            scheduleAddStartingWindow();
-            return true;
-        }
-
-        // TODO: Transfer thumbnail
-
-        return false;
-    }
-
-    boolean isLastWindow(WindowState win) {
-        return mChildren.size() == 1 && mChildren.get(0) == win;
-    }
-
-    @Override
-    void onAppTransitionDone() {
-        sendingToBottom = false;
-    }
-
-    /**
-     * We override because this class doesn't want its children affecting its reported orientation
-     * in anyway.
-     */
-    @Override
-    int getOrientation(int candidate) {
-        if (candidate == SCREEN_ORIENTATION_BEHIND) {
-            // Allow app to specify orientation regardless of its visibility state if the current
-            // candidate want us to use orientation behind. I.e. the visible app on-top of this one
-            // wants us to use the orientation of the app behind it.
-            return mOrientation;
-        }
-
-        // The {@link AppWindowToken} should only specify an orientation when it is not closing or
-        // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
-        // an Activity in another task being started in the wrong orientation during the transition.
-        if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
-                && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
-            return mOrientation;
-        }
-
-        return SCREEN_ORIENTATION_UNSET;
-    }
-
-    /** Returns the app's preferred orientation regardless of its currently visibility state. */
-    int getRequestedOrientation() {
-        return mOrientation;
-    }
-
-    /** @return {@code true} if the compatibility bounds is taking effect. */
-    boolean hasSizeCompatBounds() {
-        return mSizeCompatBounds != null;
-    }
-
-    @Override
-    float getSizeCompatScale() {
-        return hasSizeCompatBounds() ? mSizeCompatScale : super.getSizeCompatScale();
-    }
-
-    @Override
-    public void onConfigurationChanged(Configuration newParentConfig) {
-        final int prevWinMode = getWindowingMode();
-        mTmpPrevBounds.set(getBounds());
-        super.onConfigurationChanged(newParentConfig);
-
-        final Task task = getTask();
-        final Rect overrideBounds = getResolvedOverrideBounds();
-        if (task != null && !overrideBounds.isEmpty()
-                // If the changes come from change-listener, the incoming parent configuration is
-                // still the old one. Make sure their orientations are the same to reduce computing
-                // the compatibility bounds for the intermediate state.
-                && (task.mTaskRecord == null || task.mTaskRecord
-                        .getConfiguration().orientation == newParentConfig.orientation)) {
-            final Rect taskBounds = task.getBounds();
-            // Since we only center the activity horizontally, if only the fixed height is smaller
-            // than its container, the override bounds don't need to take effect.
-            if ((overrideBounds.width() != taskBounds.width()
-                    || overrideBounds.height() > taskBounds.height())) {
-                calculateCompatBoundsTransformation(newParentConfig);
-                updateSurfacePosition();
-            } else if (mSizeCompatBounds != null) {
-                mSizeCompatBounds = null;
-                mSizeCompatScale = 1f;
-                updateSurfacePosition();
-            }
-        }
-
-        final int winMode = getWindowingMode();
-
-        if (prevWinMode == winMode || mDisplayContent == null) {
-            return;
-        }
-
-        if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
-                && !isHidden()) {
-            // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
-            // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
-            final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
-            if (pinnedStack != null) {
-                final Rect stackBounds;
-                if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
-                    // We are animating the bounds, use the pre-animation bounds to save the snap
-                    // fraction
-                    stackBounds = pinnedStack.mPreAnimationBounds;
-                } else {
-                    // We skip the animation if the fullscreen configuration is not compatible, so
-                    // use the current bounds to calculate the saved snap fraction instead
-                    // (see PinnedActivityStack.skipResizeAnimation())
-                    stackBounds = mTmpRect;
-                    pinnedStack.getBounds(stackBounds);
-                }
-                mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(
-                        mActivityComponent, stackBounds);
-            }
-        } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
-            initializeChangeTransition(mTmpPrevBounds);
-        }
-    }
-
-    private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
-        if (mWmService.mDisableTransitionAnimation
-                || !isVisible()
-                || getDisplayContent().mAppTransition.isTransitionSet()
-                || getSurfaceControl() == null) {
-            return false;
-        }
-        // Only do an animation into and out-of freeform mode for now. Other mode
-        // transition animations are currently handled by system-ui.
-        return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
-    }
-
-    /**
-     * Initializes a change transition. Because the app is visible already, there is a small period
-     * of time where the user can see the app content/window update before the transition starts.
-     * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
-     * "freezes" the location/crop until the transition starts.
-     * <p>
-     * Here's a walk-through of the process:
-     * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
-     * 2. Set the temporary leash's position/crop to the current state.
-     * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
-     * 4. Once the transition is ready, it will reparent the app to the animation leash.
-     * 5. Detach the interim-change-leash.
-     */
-    private void initializeChangeTransition(Rect startBounds) {
-        mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
-                false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
-        mDisplayContent.mChangingApps.add(this);
-        mTransitStartRect.set(startBounds);
-
-        final SurfaceControl.Builder builder = makeAnimationLeash()
-                .setParent(getAnimationLeashParent())
-                .setName(getSurfaceControl() + " - interim-change-leash");
-        mTransitChangeLeash = builder.build();
-        Transaction t = getPendingTransaction();
-        t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
-        t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
-        t.show(mTransitChangeLeash);
-        t.reparent(getSurfaceControl(), mTransitChangeLeash);
-        onAnimationLeashCreated(t, mTransitChangeLeash);
-
-        // Skip creating snapshot if this transition is controlled by a remote animator which
-        // doesn't need it.
-        ArraySet<Integer> activityTypes = new ArraySet<>();
-        activityTypes.add(getActivityType());
-        RemoteAnimationAdapter adapter =
-                mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
-                        this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
-        if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
-            return;
-        }
-
-        Task task = getTask();
-        if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
-            SurfaceControl.ScreenshotGraphicBuffer snapshot =
-                    mWmService.mTaskSnapshotController.createTaskSnapshot(
-                            task, 1 /* scaleFraction */);
-            if (snapshot != null) {
-                mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, t, this,
-                        snapshot.getGraphicBuffer(), true /* relative */);
-            }
-        }
-    }
-
-    boolean isInChangeTransition() {
-        return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
-    }
-
-    @VisibleForTesting
-    AppWindowThumbnail getThumbnail() {
-        return mThumbnail;
-    }
-
-    /**
-     * Calculates the scale and offset to horizontal center the size compatibility bounds into the
-     * region which is available to application.
-     */
-    private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
-        final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
-        final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
-        final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
-        final Rect appBounds = getWindowConfiguration().getAppBounds();
-        final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
-        final float contentW = contentBounds.width();
-        final float contentH = contentBounds.height();
-        final float viewportW = viewportBounds.width();
-        final float viewportH = viewportBounds.height();
-        // Only allow to scale down.
-        mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
-                ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
-        final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
-                + viewportBounds.left;
-
-        if (mSizeCompatBounds == null) {
-            mSizeCompatBounds = new Rect();
-        }
-        mSizeCompatBounds.set(contentBounds);
-        mSizeCompatBounds.offsetTo(0, 0);
-        mSizeCompatBounds.scale(mSizeCompatScale);
-        // Ensure to align the top with the parent.
-        mSizeCompatBounds.top = parentBounds.top;
-        // The decor inset is included in height.
-        mSizeCompatBounds.bottom += viewportBounds.top;
-        mSizeCompatBounds.left += offsetX;
-        mSizeCompatBounds.right += offsetX;
-    }
-
-    @Override
-    public Rect getBounds() {
-        if (mSizeCompatBounds != null) {
-            return mSizeCompatBounds;
-        }
-        return super.getBounds();
-    }
-
-    @Override
-    public boolean matchParentBounds() {
-        if (super.matchParentBounds()) {
-            return true;
-        }
-        // An activity in size compatibility mode may have override bounds which equals to its
-        // parent bounds, so the exact bounds should also be checked.
-        final WindowContainer parent = getParent();
-        return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
-    }
-
-    @Override
-    void checkAppWindowsReadyToShow() {
-        if (allDrawn == mLastAllDrawn) {
-            return;
-        }
-
-        mLastAllDrawn = allDrawn;
-        if (!allDrawn) {
-            return;
-        }
-
-        // The token has now changed state to having all windows shown...  what to do, what to do?
-        if (mFreezingScreen) {
-            showAllWindowsLocked();
-            stopFreezingScreen(false, true);
-            ProtoLog.i(WM_DEBUG_ORIENTATION,
-                            "Setting mOrientationChangeComplete=true because wtoken %s "
-                                    + "numInteresting=%d numDrawn=%d",
-                            this, mNumInterestingWindows, mNumDrawnWindows);
-            // This will set mOrientationChangeComplete and cause a pass through layout.
-            setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
-                    "checkAppWindowsReadyToShow: freezingScreen");
-        } else {
-            setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
-
-            // We can now show all of the drawn windows!
-            if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
-                showAllWindowsLocked();
-            }
-        }
-    }
-
-    /**
-     * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
-     * child {@link WindowState}. A child is considered if it has been passed into
-     * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
-     * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
-     * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
-     *
-     * @return {@code true} If all children have been considered, {@code false}.
-     */
-    private boolean allDrawnStatesConsidered() {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final WindowState child = mChildren.get(i);
-            if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     *  Determines if the token has finished drawing. This should only be called from
-     *  {@link DisplayContent#applySurfaceChangesTransaction}
-     */
-    void updateAllDrawn() {
-        if (!allDrawn) {
-            // Number of drawn windows can be less when a window is being relaunched, wait for
-            // all windows to be launched and drawn for this token be considered all drawn.
-            final int numInteresting = mNumInterestingWindows;
-
-            // We must make sure that all present children have been considered (determined by
-            // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
-            // drawn.
-            if (numInteresting > 0 && allDrawnStatesConsidered()
-                    && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
-                if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
-                        + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
-                allDrawn = true;
-                // Force an additional layout pass where
-                // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
-                if (mDisplayContent != null) {
-                    mDisplayContent.setLayoutNeeded();
-                }
-                mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
-
-                // Notify the pinned stack upon all windows drawn. If there was an animation in
-                // progress then this signal will resume that animation.
-                final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
-                if (pinnedStack != null) {
-                    pinnedStack.onAllWindowsDrawn();
-                }
-            }
-        }
-    }
-
-    // Mostly implemented in ActivityRecord...
-    boolean keyDispatchingTimedOut(String reason, int windowPid) {
-        return false;
-    }
-
-    /**
-     * Updated this app token tracking states for interesting and drawn windows based on the window.
-     *
-     * @return Returns true if the input window is considered interesting and drawn while all the
-     *         windows in this app token where not considered drawn as of the last pass.
-     */
-    boolean updateDrawnWindowStates(WindowState w) {
-        w.setDrawnStateEvaluated(true /*evaluated*/);
-
-        if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
-            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
-                    + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
-        }
-
-        if (allDrawn && !mFreezingScreen) {
-            return false;
-        }
-
-        if (mLastTransactionSequence != mWmService.mTransactionSequence) {
-            mLastTransactionSequence = mWmService.mTransactionSequence;
-            mNumDrawnWindows = 0;
-            startingDisplayed = false;
-
-            // There is the main base application window, even if it is exiting, wait for it
-            mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
-        }
-
-        final WindowStateAnimator winAnimator = w.mWinAnimator;
-
-        boolean isInterestingAndDrawn = false;
-
-        if (!allDrawn && w.mightAffectAllDrawn()) {
-            if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
-                Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
-                        + ", isAnimationSet=" + isSelfAnimating());
-                if (!w.isDrawnLw()) {
-                    Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
-                            + " pv=" + w.isVisibleByPolicy()
-                            + " mDrawState=" + winAnimator.drawStateToString()
-                            + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
-                            + " a=" + isSelfAnimating());
-                }
-            }
-
-            if (w != startingWindow) {
-                if (w.isInteresting()) {
-                    // Add non-main window as interesting since the main app has already been added
-                    if (findMainWindow(false /* includeStartingApp */) != w) {
-                        mNumInterestingWindows++;
-                    }
-                    if (w.isDrawnLw()) {
-                        mNumDrawnWindows++;
-
-                        if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
-                            Slog.v(TAG, "tokenMayBeDrawn: "
-                                    + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
-                                    + " freezingScreen=" + mFreezingScreen
-                                    + " mAppFreezing=" + w.mAppFreezing);
-                        }
-
-                        isInterestingAndDrawn = true;
-                    }
-                }
-            } else if (w.isDrawnLw()) {
-                onStartingWindowDrawn(SystemClock.uptimeMillis());
-                startingDisplayed = true;
-            }
-        }
-
-        return isInterestingAndDrawn;
-    }
-
-    /** Called when the starting window for this container is drawn. */
-    private void onStartingWindowDrawn(long timestamp) {
-        synchronized (mAtmService.mGlobalLock) {
-            mAtmService.mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
-                    getWindowingMode(), timestamp);
-        }
-    }
-
-    void layoutLetterbox(WindowState winHint) {
-        final WindowState w = findMainWindow();
-        if (w == null || winHint != null && w != winHint) {
-            return;
-        }
-        final boolean surfaceReady = w.isDrawnLw()  // Regular case
-                || w.mWinAnimator.mSurfaceDestroyDeferred  // The preserved surface is still ready.
-                || w.isDragResizeChanged();  // Waiting for relayoutWindow to call preserveSurface.
-        final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
-        if (needsLetterbox) {
-            if (mLetterbox == null) {
-                mLetterbox = new Letterbox(() -> makeChildSurface(null),
-                        mWmService.mTransactionFactory);
-                mLetterbox.attachInput(w);
-            }
-            getPosition(mTmpPoint);
-            // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
-            // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
-            // is also applied to the task).
-            Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
-                    ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
-            mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
-        } else if (mLetterbox != null) {
-            mLetterbox.hide();
-        }
-    }
-
-    void updateLetterboxSurface(WindowState winHint) {
-        final WindowState w = findMainWindow();
-        if (w != winHint && winHint != null && w != null) {
-            return;
-        }
-        layoutLetterbox(winHint);
-        if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
-            mLetterbox.applySurfaceChanges(getPendingTransaction());
-        }
-    }
-
-    @Override
-    boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
-        // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
-        // before the non-exiting app tokens. So, we skip the exiting app tokens here.
-        // TODO: Investigate if we need to continue to do this or if we can just process them
-        // in-order.
-        if (mIsExiting && !waitingForReplacement()) {
-            return false;
-        }
-        return forAllWindowsUnchecked(callback, traverseTopToBottom);
-    }
-
-    @Override
-    void forAllAppWindows(Consumer<AppWindowToken> callback) {
-        callback.accept(this);
-    }
-
-    boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
-            boolean traverseTopToBottom) {
-        return super.forAllWindows(callback, traverseTopToBottom);
-    }
-
-    @Override
-    AppWindowToken asAppWindowToken() {
-        // I am an app window token!
-        return this;
-    }
-
-    boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
-            CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
-            IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
-            boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
-        // If the display is frozen, we won't do anything until the actual window is
-        // displayed so there is no reason to put in the starting window.
-        if (!okToDisplay()) {
-            return false;
-        }
-
-        if (mStartingData != null) {
-            return false;
-        }
-
-        final WindowState mainWin = findMainWindow();
-        if (mainWin != null && mainWin.mWinAnimator.getShown()) {
-            // App already has a visible window...why would you want a starting window?
-            return false;
-        }
-
-        final ActivityManager.TaskSnapshot snapshot =
-                mWmService.mTaskSnapshotController.getSnapshot(
-                        getTask().mTaskId, getTask().mUserId,
-                        false /* restoreFromDisk */, false /* reducedResolution */);
-        final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
-                allowTaskSnapshot, activityCreated, fromRecents, snapshot);
-
-        if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
-            return createSnapshot(snapshot);
-        }
-
-        // If this is a translucent window, then don't show a starting window -- the current
-        // effect (a full-screen opaque starting window that fades away to the real contents
-        // when it is ready) does not work for this.
-        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Checking theme of starting window: 0x%x", theme);
-        if (theme != 0) {
-            AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
-                    com.android.internal.R.styleable.Window,
-                    mWmService.mCurrentUserId);
-            if (ent == null) {
-                // Whoops!  App doesn't exist. Um. Okay. We'll just pretend like we didn't
-                // see that.
-                return false;
-            }
-            final boolean windowIsTranslucent = ent.array.getBoolean(
-                    com.android.internal.R.styleable.Window_windowIsTranslucent, false);
-            final boolean windowIsFloating = ent.array.getBoolean(
-                    com.android.internal.R.styleable.Window_windowIsFloating, false);
-            final boolean windowShowWallpaper = ent.array.getBoolean(
-                    com.android.internal.R.styleable.Window_windowShowWallpaper, false);
-            final boolean windowDisableStarting = ent.array.getBoolean(
-                    com.android.internal.R.styleable.Window_windowDisablePreview, false);
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Translucent=%s Floating=%s ShowWallpaper=%s",
-                        windowIsTranslucent, windowIsFloating, windowShowWallpaper);
-            if (windowIsTranslucent) {
-                return false;
-            }
-            if (windowIsFloating || windowDisableStarting) {
-                return false;
-            }
-            if (windowShowWallpaper) {
-                if (getDisplayContent().mWallpaperController
-                        .getWallpaperTarget() == null) {
-                    // If this theme is requesting a wallpaper, and the wallpaper
-                    // is not currently visible, then this effectively serves as
-                    // an opaque window and our starting window transition animation
-                    // can still work.  We just need to make sure the starting window
-                    // is also showing the wallpaper.
-                    windowFlags |= FLAG_SHOW_WALLPAPER;
-                } else {
-                    return false;
-                }
-            }
-        }
-
-        if (transferStartingWindow(transferFrom)) {
-            return true;
-        }
-
-        // There is no existing starting window, and we don't want to create a splash screen, so
-        // that's it!
-        if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
-            return false;
-        }
-
-        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
-        mStartingData = new SplashScreenStartingData(mWmService, pkg,
-                theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
-                getMergedOverrideConfiguration());
-        scheduleAddStartingWindow();
-        return true;
-    }
-
-
-    private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
-        if (snapshot == null) {
-            return false;
-        }
-
-        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
-        mStartingData = new SnapshotStartingData(mWmService, snapshot);
-        scheduleAddStartingWindow();
-        return true;
-    }
-
-    void scheduleAddStartingWindow() {
-        // Note: we really want to do sendMessageAtFrontOfQueue() because we
-        // want to process the message ASAP, before any other queued
-        // messages.
-        if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Enqueueing ADD_STARTING");
-            mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
-        }
-    }
-
-    private final Runnable mAddStartingWindow = new Runnable() {
-
-        @Override
-        public void run() {
-            // Can be accessed without holding the global lock
-            final StartingData startingData;
-            synchronized (mWmService.mGlobalLock) {
-                // There can only be one adding request, silly caller!
-                mWmService.mAnimationHandler.removeCallbacks(this);
-
-                if (mStartingData == null) {
-                    // Animation has been canceled... do nothing.
-                    ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
-                            "startingData was nulled out before handling"
-                                + " mAddStartingWindow: %s", AppWindowToken.this);
-                    return;
-                }
-                startingData = mStartingData;
-            }
-
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Add starting %s: startingData=%s",
-                    this, startingData);
-
-
-            WindowManagerPolicy.StartingSurface surface = null;
-            try {
-                surface = startingData.createStartingSurface(AppWindowToken.this);
-            } catch (Exception e) {
-                Slog.w(TAG, "Exception when adding starting window", e);
-            }
-            if (surface != null) {
-                boolean abort = false;
-                synchronized (mWmService.mGlobalLock) {
-                    // If the window was successfully added, then
-                    // we need to remove it.
-                    if (removed || mStartingData == null) {
-                        ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
-                                "Aborted starting %s: removed=%b startingData=%s",
-                                    AppWindowToken.this, removed, mStartingData);
-
-                        startingWindow = null;
-                        mStartingData = null;
-                        abort = true;
-                    } else {
-                        startingSurface = surface;
-                    }
-                    if (!abort) {
-                        ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
-                                "Added starting %s: startingWindow=%s startingView=%s",
-                                AppWindowToken.this, startingWindow, startingSurface);
-                    }
-                }
-                if (abort) {
-                    surface.remove();
-                }
-            } else {
-                ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Surface returned was null: %s",
-                        AppWindowToken.this);
-            }
-        }
-    };
-
-    private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
-            boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
-            ActivityManager.TaskSnapshot snapshot) {
-        if (getDisplayContent().mAppTransition.getAppTransition()
-                == TRANSIT_DOCK_TASK_FROM_RECENTS) {
-            // TODO(b/34099271): Remove this statement to add back the starting window and figure
-            // out why it causes flickering, the starting window appears over the thumbnail while
-            // the docked from recents transition occurs
-            return STARTING_WINDOW_TYPE_NONE;
-        } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
-            return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
-        } else if (taskSwitch && allowTaskSnapshot) {
-            if (mWmService.mLowRamTaskSnapshotsAndRecents) {
-                // For low RAM devices, we use the splash screen starting window instead of the
-                // task snapshot starting window.
-                return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
-            }
-            return snapshot == null ? STARTING_WINDOW_TYPE_NONE
-                    : snapshotOrientationSameAsTask(snapshot) || fromRecents
-                            ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
-        } else {
-            return STARTING_WINDOW_TYPE_NONE;
-        }
-    }
-
-
-    private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
-        if (snapshot == null) {
-            return false;
-        }
-        return getTask().getConfiguration().orientation == snapshot.getOrientation();
-    }
-
-    void removeStartingWindow() {
-        if (startingWindow == null) {
-            if (mStartingData != null) {
-                // Starting window has not been added yet, but it is scheduled to be added.
-                // Go ahead and cancel the request.
-                ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Clearing startingData for token=%s", this);
-                mStartingData = null;
-            }
-            return;
-        }
-
-        final WindowManagerPolicy.StartingSurface surface;
-        if (mStartingData != null) {
-            surface = startingSurface;
-            mStartingData = null;
-            startingSurface = null;
-            startingWindow = null;
-            startingDisplayed = false;
-            if (surface == null) {
-                ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
-                        "startingWindow was set but startingSurface==null, couldn't "
-                            + "remove");
-
-                return;
-            }
-        } else {
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
-                    "Tried to remove starting window but startingWindow was null: %s",
-                        this);
-            return;
-        }
-
-        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
-                    + " startingView=%s Callers=%s",
-                    this, startingWindow, startingSurface, Debug.getCallers(5));
-
-
-        // Use the same thread to remove the window as we used to add it, as otherwise we end up
-        // with things in the view hierarchy being called from different threads.
-        mWmService.mAnimationHandler.post(() -> {
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing startingView=%s", surface);
-            try {
-                surface.remove();
-            } catch (Exception e) {
-                Slog.w(TAG_WM, "Exception when removing starting window", e);
-            }
-        });
-    }
-
-    @Override
-    boolean fillsParent() {
-        return occludesParent();
-    }
-
-    /** Returns true if this activity is opaque and fills the entire space of this task. */
-    boolean occludesParent() {
-        return mOccludesParent;
-    }
-
-    boolean setOccludesParent(boolean occludesParent) {
-        final boolean changed = occludesParent != mOccludesParent;
-        mOccludesParent = occludesParent;
-        setMainWindowOpaque(occludesParent);
-        mWmService.mWindowPlacerLocked.requestTraversal();
-        return changed;
-    }
-
-    void setMainWindowOpaque(boolean isOpaque) {
-        final WindowState win = findMainWindow();
-        if (win == null) {
-            return;
-        }
-        isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
-        win.mWinAnimator.setOpaqueLocked(isOpaque);
-    }
-
-    boolean containsDismissKeyguardWindow() {
-        // Window state is transient during relaunch. We are not guaranteed to be frozen during the
-        // entirety of the relaunch.
-        if (isRelaunching()) {
-            return mLastContainsDismissKeyguardWindow;
-        }
-
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    boolean containsShowWhenLockedWindow() {
-        // When we are relaunching, it is possible for us to be unfrozen before our previous
-        // windows have been added back. Using the cached value ensures that our previous
-        // showWhenLocked preference is honored until relaunching is complete.
-        if (isRelaunching()) {
-            return mLastContainsShowWhenLockedWindow;
-        }
-
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    void setShowWhenLocked(boolean showWhenLocked) {
-        mShowWhenLocked = showWhenLocked;
-        mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
-                0 /* configChanges */, false /* preserveWindows */);
-    }
-
-    void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
-        mInheritShownWhenLocked = inheritShowWhenLocked;
-        mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
-                0 /* configChanges */, false /* preserveWindows */);
-    }
-
-    /**
-     * @return {@code true} if the activity windowing mode is not
-     *         {@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
-     *         {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
-     *         conditions a) above.
-     *         Multi-windowing mode will be exited if {@code true} is returned.
-     */
-    boolean canShowWhenLocked() {
-        if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
-            return true;
-        } else if (mInheritShownWhenLocked) {
-            final AppWindowToken r = getActivityBelow();
-            return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
-                    || r.containsShowWhenLockedWindow());
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
-     * such activity exists.
-     */
-    @Nullable
-    private AppWindowToken getActivityBelow() {
-        final Task task = getTask();
-        final int pos = task.mChildren.indexOf(this);
-        if (pos == -1) {
-            throw new IllegalStateException("Activity not found in its task");
-        }
-        return pos == 0 ? null : task.getChildAt(pos - 1);
-    }
-
-    void setTurnScreenOn(boolean turnScreenOn) {
-        mTurnScreenOn = turnScreenOn;
-    }
-
-    /** Mostly implemented in ActivityRecord. */
-    boolean canTurnScreenOn() {
-        return mTurnScreenOn;
-    }
-
-    boolean getTurnScreenOnFlag() {
-        return mTurnScreenOn;
-    }
-
-    void checkKeyguardFlagsChanged() {
-        final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
-        final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
-        if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
-                || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
-            mWmService.notifyKeyguardFlagsChanged(null /* callback */,
-                    getDisplayContent().getDisplayId());
-        }
-        mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
-        mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
-    }
-
-    WindowState getImeTargetBelowWindow(WindowState w) {
-        final int index = mChildren.indexOf(w);
-        if (index > 0) {
-            final WindowState target = mChildren.get(index - 1);
-            if (target.canBeImeTarget()) {
-                return target;
-            }
-        }
-        return null;
-    }
-
-    WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
-        WindowState candidate = null;
-        for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
-            final WindowState w = mChildren.get(i);
-            if (w.mRemoved) {
-                continue;
-            }
-            if (candidate == null) {
-                candidate = w;
-            }
-        }
-        return candidate;
-    }
-
-    /**
-     * See {@link Activity#setDisablePreviewScreenshots}.
-     */
-    void setDisablePreviewScreenshots(boolean disable) {
-        mDisablePreviewScreenshots = disable;
-    }
-
-    /**
-     * Sets whether the current launch can turn the screen on.
-     * @see #currentLaunchCanTurnScreenOn()
-     */
-    void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
-        mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
-    }
-
-    /**
-     * Indicates whether the current launch can turn the screen on. This is to prevent multiple
-     * relayouts from turning the screen back on. The screen should only turn on at most
-     * once per activity resume.
-     * <p>
-     * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
-     * or {@link ActivityRecord#canTurnScreenOn} is set.
-     *
-     * @return {@code true} if the activity is ready to turn on the screen.
-     */
-    boolean currentLaunchCanTurnScreenOn() {
-        return mCurrentLaunchCanTurnScreenOn;
-    }
-
-    /**
-     * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
-     * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
-     * we can't take a snapshot for other reasons, for example, if we have a secure window.
-     *
-     * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
-     *         screenshot.
-     */
-    boolean shouldUseAppThemeSnapshot() {
-        return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
-                true /* topToBottom */);
-    }
-
-    SurfaceControl getAppAnimationLayer() {
-        return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
-                : needsZBoost() ? ANIMATION_LAYER_BOOSTED
-                : ANIMATION_LAYER_STANDARD);
-    }
-
-    @Override
-    public SurfaceControl getAnimationLeashParent() {
-        // For transitions in the pinned stack (menu activity) we just let them occur as a child
-        // of the pinned stack.
-        // All normal app transitions take place in an animation layer which is below the pinned
-        // stack but may be above the parent stacks of the given animating apps by default. When
-        // a new hierarchical animation is enabled, we just let them occur as a child of the parent
-        // stack, i.e. the hierarchy of the surfaces is unchanged.
-        if (inPinnedWindowingMode()) {
-            return getStack().getSurfaceControl();
-        } else if (WindowManagerService.sHierarchicalAnimations) {
-            return super.getAnimationLeashParent();
-        } else {
-            return getAppAnimationLayer();
-        }
-    }
-
-
-    @VisibleForTesting
-    boolean shouldAnimate(int transit) {
-        final boolean isSplitScreenPrimary =
-                getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-        final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
-
-        // Don't animate while the task runs recents animation but only if we are in the mode
-        // where we cancel with deferred screenshot, which means that the controller has
-        // transformed the task.
-        final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
-        if (controller != null && controller.isAnimatingTask(getTask())
-                && controller.shouldDeferCancelUntilNextTransition()) {
-            return false;
-        }
-
-        // We animate always if it's not split screen primary, and only some special cases in split
-        // screen primary because it causes issues with stack clipping when we run an un-minimize
-        // animation at the same time.
-        return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
-    }
-
-    /**
-     * Creates a layer to apply crop to an animation.
-     */
-    private SurfaceControl createAnimationBoundsLayer(Transaction t) {
-        ProtoLog.i(WM_DEBUG_APP_TRANSITIONS_ANIM, "Creating animation bounds layer");
-        final SurfaceControl.Builder builder = makeAnimationLeash()
-                .setParent(getAnimationLeashParent())
-                .setName(getSurfaceControl() + " - animation-bounds");
-        final SurfaceControl boundsLayer = builder.build();
-        t.show(boundsLayer);
-        return boundsLayer;
-    }
-
-    @Override
-    Rect getDisplayedBounds() {
-        final Task task = getTask();
-        if (task != null) {
-            final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
-            if (!overrideDisplayedBounds.isEmpty()) {
-                return overrideDisplayedBounds;
-            }
-        }
-        return getBounds();
-    }
-
-    @VisibleForTesting
-    Rect getAnimationBounds(int appStackClipMode) {
-        if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
-            // Using the stack bounds here effectively applies the clipping before animation.
-            return getStack().getBounds();
-        }
-        // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
-        // included in the animation.
-        return getTask() != null ? getTask().getBounds() : getBounds();
-    }
-
-    boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
-            boolean isVoiceInteraction) {
-
-        if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
-            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
-                    "applyAnimation: transition animation is disabled or skipped. "
-                            + "atoken=%s", this);
-            cancelAnimation();
-            return false;
-        }
-
-        // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
-        // to animate and it can cause strange artifacts when we unfreeze the display if some
-        // different animation is running.
-        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
-        if (okToAnimate()) {
-            final AnimationAdapter adapter;
-            AnimationAdapter thumbnailAdapter = null;
-
-            final int appStackClipMode =
-                    getDisplayContent().mAppTransition.getAppStackClipMode();
-
-            // Separate position and size for use in animators.
-            mTmpRect.set(getAnimationBounds(appStackClipMode));
-            mTmpPoint.set(mTmpRect.left, mTmpRect.top);
-            mTmpRect.offsetTo(0, 0);
-
-            final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
-                    && getDisplayContent().mChangingApps.contains(this);
-
-            // Delaying animation start isn't compatible with remote animations at all.
-            if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
-                    && !mSurfaceAnimator.isAnimationStartDelayed()) {
-                RemoteAnimationRecord adapters =
-                        getDisplayContent().mAppTransition.getRemoteAnimationController()
-                                .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
-                                        (isChanging ? mTransitStartRect : null));
-                adapter = adapters.mAdapter;
-                thumbnailAdapter = adapters.mThumbnailAdapter;
-            } else if (isChanging) {
-                final float durationScale = mWmService.getTransitionAnimationScaleLocked();
-                mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
-                adapter = new LocalAnimationAdapter(
-                        new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
-                                getDisplayContent().getDisplayInfo(), durationScale,
-                                true /* isAppAnimation */, false /* isThumbnail */),
-                        mWmService.mSurfaceAnimationRunner);
-                if (mThumbnail != null) {
-                    thumbnailAdapter = new LocalAnimationAdapter(
-                            new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
-                                    getDisplayContent().getDisplayInfo(), durationScale,
-                                    true /* isAppAnimation */, true /* isThumbnail */),
-                            mWmService.mSurfaceAnimationRunner);
-                }
-                mTransit = transit;
-                mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
-            } else {
-                mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
-
-                final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
-                if (a != null) {
-                    // Only apply corner radius to animation if we're not in multi window mode.
-                    // We don't want rounded corners when in pip or split screen.
-                    final float windowCornerRadius = !inMultiWindowMode()
-                            ? getDisplayContent().getWindowCornerRadius()
-                            : 0;
-                    adapter = new LocalAnimationAdapter(
-                            new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
-                                    getDisplayContent().mAppTransition.canSkipFirstFrame(),
-                                    appStackClipMode,
-                                    true /* isAppAnimation */,
-                                    windowCornerRadius),
-                            mWmService.mSurfaceAnimationRunner);
-                    if (a.getZAdjustment() == Animation.ZORDER_TOP) {
-                        mNeedsZBoost = true;
-                    }
-                    mTransit = transit;
-                    mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
-                } else {
-                    adapter = null;
-                }
-            }
-            if (adapter != null) {
-                startAnimation(getPendingTransaction(), adapter, !isVisible());
-                if (adapter.getShowWallpaper()) {
-                    mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-                }
-                if (thumbnailAdapter != null) {
-                    mThumbnail.startAnimation(
-                            getPendingTransaction(), thumbnailAdapter, !isVisible());
-                }
-            }
-        } else {
-            cancelAnimation();
-        }
-        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
-
-        return isReallyAnimating();
-    }
-
-    private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
-            boolean isVoiceInteraction) {
-        final DisplayContent displayContent = getTask().getDisplayContent();
-        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-        final int width = displayInfo.appWidth;
-        final int height = displayInfo.appHeight;
-        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
-                "applyAnimation: atoken=%s", this);
-
-        // Determine the visible rect to calculate the thumbnail clip
-        final WindowState win = findMainWindow();
-        final Rect frame = new Rect(0, 0, width, height);
-        final Rect displayFrame = new Rect(0, 0,
-                displayInfo.logicalWidth, displayInfo.logicalHeight);
-        final Rect insets = new Rect();
-        final Rect stableInsets = new Rect();
-        Rect surfaceInsets = null;
-        final boolean freeform = win != null && win.inFreeformWindowingMode();
-        if (win != null) {
-            // Containing frame will usually cover the whole screen, including dialog windows.
-            // For freeform workspace windows it will not cover the whole screen and it also
-            // won't exactly match the final freeform window frame (e.g. when overlapping with
-            // the status bar). In that case we need to use the final frame.
-            if (freeform) {
-                frame.set(win.getFrameLw());
-            } else if (win.isLetterboxedAppWindow()) {
-                frame.set(getTask().getBounds());
-            } else if (win.isDockedResizing()) {
-                // If we are animating while docked resizing, then use the stack bounds as the
-                // animation target (which will be different than the task bounds)
-                frame.set(getTask().getParent().getBounds());
-            } else {
-                frame.set(win.getContainingFrame());
-            }
-            surfaceInsets = win.getAttrs().surfaceInsets;
-            // XXX(b/72757033): These are insets relative to the window frame, but we're really
-            // interested in the insets relative to the frame we chose in the if-blocks above.
-            win.getContentInsets(insets);
-            win.getStableInsets(stableInsets);
-        }
-
-        if (mLaunchTaskBehind) {
-            // Differentiate the two animations. This one which is briefly on the screen
-            // gets the !enter animation, and the other activity which remains on the
-            // screen gets the enter animation. Both appear in the mOpeningApps set.
-            enter = false;
-        }
-        ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
-                "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
-                        + "surfaceInsets=%s",
-                AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
-        final Configuration displayConfig = displayContent.getConfiguration();
-        final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
-                displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
-                surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
-        if (a != null) {
-            if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
-            final int containingWidth = frame.width();
-            final int containingHeight = frame.height();
-            a.initialize(containingWidth, containingHeight, width, height);
-            a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
-        }
-        return a;
-    }
-
-    @Override
-    public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
-        return mAnimatingAppWindowTokenRegistry != null
-                && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
-                        this, endDeferFinishCallback);
-    }
-
-    @Override
-    public void onAnimationLeashLost(Transaction t) {
-        super.onAnimationLeashLost(t);
-        if (mAnimationBoundsLayer != null) {
-            t.remove(mAnimationBoundsLayer);
-            mAnimationBoundsLayer = null;
-        }
-
-        if (mAnimatingAppWindowTokenRegistry != null) {
-            mAnimatingAppWindowTokenRegistry.notifyFinished(this);
-        }
-    }
-
-    @Override
-    protected void setLayer(Transaction t, int layer) {
-        if (!mSurfaceAnimator.hasLeash()) {
-            t.setLayer(mSurfaceControl, layer);
-        }
-    }
-
-    @Override
-    protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
-        if (!mSurfaceAnimator.hasLeash()) {
-            t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
-        }
-    }
-
-    @Override
-    protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
-        if (!mSurfaceAnimator.hasLeash()) {
-            t.reparent(mSurfaceControl, newParent);
-        }
-    }
-
-    @Override
-    public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
-        // The leash is parented to the animation layer. We need to preserve the z-order by using
-        // the prefix order index, but we boost if necessary.
-        int layer = 0;
-        if (!inPinnedWindowingMode()) {
-            layer = getPrefixOrderIndex();
-        } else {
-            // Pinned stacks have animations take place within themselves rather than an animation
-            // layer so we need to preserve the order relative to the stack (e.g. the order of our
-            // task/parent).
-            layer = getParent().getPrefixOrderIndex();
-        }
-
-        if (mNeedsZBoost) {
-            layer += Z_BOOST_BASE;
-        }
-        if (!mNeedsAnimationBoundsLayer) {
-            t.setLayer(leash, layer);
-        }
-
-        final DisplayContent dc = getDisplayContent();
-        dc.assignStackOrdering();
-
-        if (leash == mTransitChangeLeash) {
-            // This is a temporary state so skip any animation notifications
-            return;
-        } else if (mTransitChangeLeash != null) {
-            // unparent mTransitChangeLeash for clean-up
-            clearChangeLeash(t, false /* cancel */);
-        }
-
-        if (mAnimatingAppWindowTokenRegistry != null) {
-            mAnimatingAppWindowTokenRegistry.notifyStarting(this);
-        }
-
-        // If the animation needs to be cropped then an animation bounds layer is created as a child
-        // of the pinned stack or animation layer. The leash is then reparented to this new layer.
-        if (mNeedsAnimationBoundsLayer) {
-            mTmpRect.setEmpty();
-            final Task task = getTask();
-            if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
-                    getTransit(), task)) {
-                task.getBounds(mTmpRect);
-            } else {
-                final TaskStack stack = getStack();
-                if (stack == null) {
-                    return;
-                }
-                // Set clip rect to stack bounds.
-                stack.getBounds(mTmpRect);
-            }
-            mAnimationBoundsLayer = createAnimationBoundsLayer(t);
-
-            // Crop to stack bounds.
-            t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
-            t.setLayer(mAnimationBoundsLayer, layer);
-
-            // Reparent leash to animation bounds layer.
-            t.reparent(leash, mAnimationBoundsLayer);
-        }
-    }
-
-    /**
-     * This must be called while inside a transaction.
-     */
-    void showAllWindowsLocked() {
-        forAllWindows(windowState -> {
-            if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
-            windowState.performShowLocked();
-        }, false /* traverseTopToBottom */);
-    }
-
-    @Override
-    protected void onAnimationFinished() {
-        super.onAnimationFinished();
-
-        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
-        mTransit = TRANSIT_UNSET;
-        mTransitFlags = 0;
-        mNeedsZBoost = false;
-        mNeedsAnimationBoundsLayer = false;
-
-        setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
-                "AppWindowToken");
-
-        clearThumbnail();
-        setClientHidden(isHidden() && hiddenRequested);
-
-        getDisplayContent().computeImeTargetIfNeeded(this);
-
-        if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
-                + ": reportedVisible=" + reportedVisible
-                + " okToDisplay=" + okToDisplay()
-                + " okToAnimate=" + okToAnimate()
-                + " startingDisplayed=" + startingDisplayed);
-
-        // clean up thumbnail window
-        if (mThumbnail != null) {
-            mThumbnail.destroy();
-            mThumbnail = null;
-        }
-
-        // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
-        // traverse the copy.
-        final ArrayList<WindowState> children = new ArrayList<>(mChildren);
-        children.forEach(WindowState::onExitAnimationDone);
-
-        getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
-        scheduleAnimation();
-
-        if (mAtmService.mRootActivityContainer.allResumedActivitiesIdle()
-                || mAtmService.mStackSupervisor.isStoppingNoHistoryActivity()) {
-            // If all activities are already idle or there is an activity that must be
-            // stopped immediately after visible, then we now need to make sure we perform
-            // the full stop of this activity. This is because we won't do that while they are still
-            // waiting for the animation to finish.
-            if (mAtmService.mStackSupervisor.mStoppingActivities.contains(this)) {
-                mAtmService.mStackSupervisor.scheduleIdleLocked();
-            }
-        } else {
-            // Instead of doing the full stop routine here, let's just hide any activities
-            // we now can, and let them stop when the normal idle happens.
-            mAtmService.mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
-                    false /* remove */, true /* processPausingActivities */);
-        }
-        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
-    }
-
-    @Override
-    boolean isAppAnimating() {
-        return isSelfAnimating();
-    }
-
-    @Override
-    boolean isSelfAnimating() {
-        // If we are about to start a transition, we also need to be considered animating.
-        return isWaitingForTransitionStart() || isReallyAnimating();
-    }
-
-    /**
-     * @return True if and only if we are actually running an animation. Note that
-     *         {@link #isSelfAnimating} also returns true if we are waiting for an animation to
-     *         start.
-     */
-    private boolean isReallyAnimating() {
-        return super.isSelfAnimating();
-    }
-
-    /**
-     * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
-     *                            to another leash.
-     */
-    private void clearChangeLeash(Transaction t, boolean cancel) {
-        if (mTransitChangeLeash == null) {
-            return;
-        }
-        if (cancel) {
-            clearThumbnail();
-            SurfaceControl sc = getSurfaceControl();
-            SurfaceControl parentSc = getParentSurfaceControl();
-            // Don't reparent if surface is getting destroyed
-            if (parentSc != null && sc != null) {
-                t.reparent(sc, getParentSurfaceControl());
-            }
-        }
-        t.hide(mTransitChangeLeash);
-        t.remove(mTransitChangeLeash);
-        mTransitChangeLeash = null;
-        if (cancel) {
-            onAnimationLeashLost(t);
-        }
-    }
-
-    @Override
-    void cancelAnimation() {
-        cancelAnimationOnly();
-        clearThumbnail();
-        clearChangeLeash(getPendingTransaction(), true /* cancel */);
-    }
-
-    /**
-     * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
-     * or interim leashes.
-     * <p>
-     * Used when canceling in preparation for starting a new animation.
-     */
-    void cancelAnimationOnly() {
-        super.cancelAnimation();
-    }
-
-    boolean isWaitingForTransitionStart() {
-        final DisplayContent dc = getDisplayContent();
-        // TODO: Test for null can be removed once unification is done.
-        if (dc == null) return false;
-        return dc.mAppTransition.isTransitionSet()
-                && (dc.mOpeningApps.contains(this)
-                    || dc.mClosingApps.contains(this)
-                    || dc.mChangingApps.contains(this));
-    }
-
-    public int getTransit() {
-        return mTransit;
-    }
-
-    int getTransitFlags() {
-        return mTransitFlags;
-    }
-
-    void attachThumbnailAnimation() {
-        if (!isReallyAnimating()) {
-            return;
-        }
-        final int taskId = getTask().mTaskId;
-        final GraphicBuffer thumbnailHeader =
-                getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
-        if (thumbnailHeader == null) {
-            ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %d", taskId);
-            return;
-        }
-        clearThumbnail();
-        mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, getPendingTransaction(),
-                this, thumbnailHeader);
-        mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
-    }
-
-    /**
-     * Attaches a surface with a thumbnail for the
-     * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
-     */
-    void attachCrossProfileAppsThumbnailAnimation() {
-        if (!isReallyAnimating()) {
-            return;
-        }
-        clearThumbnail();
-
-        final WindowState win = findMainWindow();
-        if (win == null) {
-            return;
-        }
-        final Rect frame = win.getFrameLw();
-        final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
-                ? R.drawable.ic_account_circle
-                : R.drawable.ic_corp_badge;
-        final GraphicBuffer thumbnail =
-                getDisplayContent().mAppTransition
-                        .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
-        if (thumbnail == null) {
-            return;
-        }
-        mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory,
-                getPendingTransaction(), this, thumbnail);
-        final Animation animation =
-                getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
-                        win.getFrameLw());
-        mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
-                frame.top));
-    }
-
-    private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
-        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
-
-        // If this is a multi-window scenario, we use the windows frame as
-        // destination of the thumbnail header animation. If this is a full screen
-        // window scenario, we use the whole display as the target.
-        WindowState win = findMainWindow();
-        Rect appRect = win != null ? win.getContentFrameLw() :
-                new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
-        final Rect insets = win != null ? win.getContentInsets() : null;
-        final Configuration displayConfig = mDisplayContent.getConfiguration();
-        return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
-                appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
-                displayConfig.orientation);
-    }
-
-    private void clearThumbnail() {
-        if (mThumbnail == null) {
-            return;
-        }
-        mThumbnail.destroy();
-        mThumbnail = null;
-    }
-
-    void registerRemoteAnimations(RemoteAnimationDefinition definition) {
-        mRemoteAnimationDefinition = definition;
-    }
-
-    RemoteAnimationDefinition getRemoteAnimationDefinition() {
-        return mRemoteAnimationDefinition;
-    }
-
-    @Override
-    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
-        super.dump(pw, prefix, dumpAll);
-        if (appToken != null) {
-            pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
-        }
-        pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
-        pw.print(prefix); pw.print("task="); pw.println(getTask());
-        pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
-                pw.print(" mOrientation="); pw.println(mOrientation);
-        pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
-            + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
-            + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
-        if (paused) {
-            pw.print(prefix); pw.print("paused="); pw.println(paused);
-        }
-        if (mAppStopped) {
-            pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
-        }
-        if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
-                || allDrawn || mLastAllDrawn) {
-            pw.print(prefix); pw.print("mNumInterestingWindows=");
-                    pw.print(mNumInterestingWindows);
-                    pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
-                    pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
-                    pw.print(" allDrawn="); pw.print(allDrawn);
-                    pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
-                    pw.println(")");
-        }
-        if (inPendingTransaction) {
-            pw.print(prefix); pw.print("inPendingTransaction=");
-                    pw.println(inPendingTransaction);
-        }
-        if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
-            pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
-                    pw.print(" removed="); pw.print(removed);
-                    pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
-                    pw.print(" mIsExiting="); pw.println(mIsExiting);
-        }
-        if (startingWindow != null || startingSurface != null
-                || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
-            pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
-                    pw.print(" startingSurface="); pw.print(startingSurface);
-                    pw.print(" startingDisplayed="); pw.print(startingDisplayed);
-                    pw.print(" startingMoved="); pw.print(startingMoved);
-                    pw.println(" mHiddenSetFromTransferredStartingWindow="
-                            + mHiddenSetFromTransferredStartingWindow);
-        }
-        if (!mFrozenBounds.isEmpty()) {
-            pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
-            pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
-        }
-        if (mPendingRelaunchCount != 0) {
-            pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
-        }
-        if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
-            pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
-                    + mSizeCompatBounds);
-        }
-        if (mRemovingFromDisplay) {
-            pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
-        }
-    }
-
-    @Override
-    void setHidden(boolean hidden) {
-        super.setHidden(hidden);
-        scheduleAnimation();
-    }
-
-    @Override
-    void prepareSurfaces() {
-        // isSelfAnimating also returns true when we are about to start a transition, so we need
-        // to check super here.
-        final boolean reallyAnimating = super.isSelfAnimating();
-        final boolean show = !isHidden() || reallyAnimating;
-
-        if (mSurfaceControl != null) {
-            if (show && !mLastSurfaceShowing) {
-                getPendingTransaction().show(mSurfaceControl);
-            } else if (!show && mLastSurfaceShowing) {
-                getPendingTransaction().hide(mSurfaceControl);
-            }
-        }
-        if (mThumbnail != null) {
-            mThumbnail.setShowing(getPendingTransaction(), show);
-        }
-        mLastSurfaceShowing = show;
-        super.prepareSurfaces();
-    }
-
-    /**
-     * @return Whether our {@link #getSurfaceControl} is currently showing.
-     */
-    boolean isSurfaceShowing() {
-        return mLastSurfaceShowing;
-    }
-
-    boolean isFreezingScreen() {
-        return mFreezingScreen;
-    }
-
-    @Override
-    boolean needsZBoost() {
-        return mNeedsZBoost || super.needsZBoost();
-    }
-
-    @CallSuper
-    @Override
-    public void writeToProto(ProtoOutputStream proto, long fieldId,
-            @WindowTraceLogLevel int logLevel) {
-        // Critical log level logs only visible elements to mitigate performance overheard
-        if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
-            return;
-        }
-
-        final long token = proto.start(fieldId);
-        writeNameToProto(proto, NAME);
-        super.writeToProto(proto, WINDOW_TOKEN, logLevel);
-        proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
-        proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
-        proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
-        if (mThumbnail != null){
-            mThumbnail.writeToProto(proto, THUMBNAIL);
-        }
-        proto.write(FILLS_PARENT, mOccludesParent);
-        proto.write(APP_STOPPED, mAppStopped);
-        proto.write(HIDDEN_REQUESTED, hiddenRequested);
-        proto.write(CLIENT_HIDDEN, mClientHidden);
-        proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
-        proto.write(REPORTED_DRAWN, reportedDrawn);
-        proto.write(REPORTED_VISIBLE, reportedVisible);
-        proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
-        proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
-        proto.write(ALL_DRAWN, allDrawn);
-        proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
-        proto.write(REMOVED, removed);
-        if (startingWindow != null) {
-            startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
-        }
-        proto.write(STARTING_DISPLAYED, startingDisplayed);
-        proto.write(STARTING_MOVED, startingMoved);
-        proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
-                mHiddenSetFromTransferredStartingWindow);
-        for (Rect bounds : mFrozenBounds) {
-            bounds.writeToProto(proto, FROZEN_BOUNDS);
-        }
-        proto.end(token);
-    }
-
-    void writeNameToProto(ProtoOutputStream proto, long fieldId) {
-        if (appToken != null) {
-            proto.write(fieldId, appToken.getName());
-        }
-    }
-
-    void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
-        final long token = proto.start(fieldId);
-        proto.write(HASH_CODE, System.identityHashCode(this));
-        proto.write(USER_ID, mUserId);
-        proto.write(TITLE, ((ActivityRecord) this).intent.getComponent().flattenToShortString());
-        proto.end(token);
-    }
-
-    Rect getLetterboxInsets() {
-        if (mLetterbox != null) {
-            return mLetterbox.getInsets();
-        } else {
-            return new Rect();
-        }
-    }
-
-    /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
-    void getLetterboxInnerBounds(Rect outBounds) {
-        if (mLetterbox != null) {
-            outBounds.set(mLetterbox.getInnerFrame());
-        } else {
-            outBounds.setEmpty();
-        }
-    }
-
-    /**
-     * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
-     * the given {@code rect}.
-     */
-    boolean isLetterboxOverlappingWith(Rect rect) {
-        return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
-    }
-
-    /**
-     * Sets if this AWT is in the process of closing or entering PIP.
-     * {@link #mWillCloseOrEnterPip}}
-     */
-    void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
-        mWillCloseOrEnterPip = willCloseOrEnterPip;
-    }
-
-    /**
-     * Returns whether this AWT is considered closing. Conditions are either
-     * 1. Is this app animating and was requested to be hidden
-     * 2. App is delayed closing since it might enter PIP.
-     */
-    boolean isClosingOrEnteringPip() {
-        return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
-    }
-
-    /**
-     * @return Whether we are allowed to show non-starting windows at the moment. We disallow
-     *         showing windows during transitions in case we have windows that have wide-color-gamut
-     *         color mode set to avoid jank in the middle of the transition.
-     */
-    boolean canShowWindows() {
-        return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
-    }
-
-    /**
-     * @return true if we have a window that has a non-default color mode set; false otherwise.
-     */
-    private boolean hasNonDefaultColorWindow() {
-        return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
-                true /* topToBottom */);
-    }
-
-    private void updateColorTransform() {
-        if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
-            getPendingTransaction().setColorTransform(mSurfaceControl,
-                    mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
-            mWmService.scheduleAnimationLocked();
-        }
-    }
-
-    private static class AppSaturationInfo {
-        float[] mMatrix = new float[9];
-        float[] mTranslation = new float[3];
-
-        void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
-            System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
-            System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 8afbbdf..300ee1d 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -626,6 +626,10 @@
         return mFullConfiguration.windowConfiguration.isAlwaysOnTop();
     }
 
+    boolean hasChild() {
+        return getChildCount() > 0;
+    }
+
     abstract protected int getChildCount();
 
     abstract protected E getChildAt(int index);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4c3611e..940e814 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -270,9 +270,9 @@
     final AppTransitionController mAppTransitionController;
     boolean mSkipAppTransitionAnimation = false;
 
-    final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>();
-    final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>();
-    final ArraySet<AppWindowToken> mChangingApps = new ArraySet<>();
+    final ArraySet<ActivityRecord> mOpeningApps = new ArraySet<>();
+    final ArraySet<ActivityRecord> mClosingApps = new ArraySet<>();
+    final ArraySet<ActivityRecord> mChangingApps = new ArraySet<>();
     final UnknownAppVisibilityController mUnknownAppVisibilityController;
     BoundsAnimationController mBoundsAnimationController;
 
@@ -438,7 +438,7 @@
     /** A collection of windows that provide tap exclude regions inside of them. */
     final ArraySet<WindowState> mTapExcludeProvidingWindows = new ArraySet<>();
 
-    private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
+    private final LinkedList<ActivityRecord> mTmpUpdateAllDrawn = new LinkedList();
 
     private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
             new TaskForResizePointSearchResult();
@@ -480,7 +480,7 @@
      * the user taps on the area outside of the task of the focused app, we will notify AM about the
      * new task the user wants to interact with.
      */
-    AppWindowToken mFocusedApp = null;
+    ActivityRecord mFocusedApp = null;
 
     /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
     final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
@@ -563,9 +563,9 @@
 
     private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
         WindowStateAnimator winAnimator = w.mWinAnimator;
-        final AppWindowToken atoken = w.mAppToken;
+        final ActivityRecord activity = w.mActivityRecord;
         if (winAnimator.mDrawState == READY_TO_SHOW) {
-            if (atoken == null || atoken.canShowWindows()) {
+            if (activity == null || activity.canShowWindows()) {
                 if (w.performShowLocked()) {
                     pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
                     if (DEBUG_LAYOUT_REPEATS) {
@@ -589,7 +589,7 @@
     };
 
     private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> {
-        final AppWindowToken focusedApp = mFocusedApp;
+        final ActivityRecord focusedApp = mFocusedApp;
         ProtoLog.v(WM_DEBUG_FOCUS, "Looking for focus: %s, flags=%d, canReceive=%b",
                 w, w.mAttrs.flags, w.canReceiveKeys());
 
@@ -597,12 +597,12 @@
             return false;
         }
 
-        final AppWindowToken wtoken = w.mAppToken;
+        final ActivityRecord activity = w.mActivityRecord;
 
         // If this window's application has been removed, just skip it.
-        if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
-            ProtoLog.v(WM_DEBUG_FOCUS, "Skipping %s because %s", wtoken,
-                    (wtoken.removed ? "removed" : "sendingToBottom"));
+        if (activity!= null && (activity.removed || activity.sendingToBottom)) {
+            ProtoLog.v(WM_DEBUG_FOCUS, "Skipping %s because %s", activity,
+                    (activity.removed ? "removed" : "sendingToBottom"));
             return false;
         }
 
@@ -622,9 +622,9 @@
         }
 
         // Descend through all of the app tokens and find the first that either matches
-        // win.mAppToken (return win) or mFocusedApp (return null).
-        if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) {
-            if (focusedApp.compareTo(wtoken) > 0) {
+        // win.mActivityRecord (return win) or mFocusedApp (return null).
+        if (activity != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) {
+            if (focusedApp.compareTo(activity) > 0) {
                 // App stack below focused app stack. No focus for you!!!
                 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
                         "findFocusedWindow: Reached focused app=%s", focusedApp);
@@ -648,14 +648,14 @@
             Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
                     + " mLayoutAttached=" + w.mLayoutAttached
                     + " config reported=" + w.isLastConfigReportedToClient());
-            final AppWindowToken atoken = w.mAppToken;
+            final ActivityRecord activity = w.mActivityRecord;
             if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + w.mViewVisibility
                     + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
-                    + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
+                    + " hiddenRequested=" + (activity != null && activity.hiddenRequested)
                     + " parentHidden=" + w.isParentWindowHidden());
             else Slog.v(TAG, "  VIS: mViewVisibility=" + w.mViewVisibility
                     + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
-                    + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
+                    + " hiddenRequested=" + (activity != null && activity.hiddenRequested)
                     + " parentHidden=" + w.isParentWindowHidden());
         }
 
@@ -683,8 +683,8 @@
                 w.updateLastInsetValues();
             }
 
-            if (w.mAppToken != null) {
-                w.mAppToken.layoutLetterbox(w);
+            if (w.mActivityRecord != null) {
+                w.mActivityRecord.layoutLetterbox(w);
             }
 
             if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.getFrameLw()
@@ -825,12 +825,12 @@
             }
         }
 
-        final AppWindowToken atoken = w.mAppToken;
-        if (atoken != null) {
-            atoken.updateLetterboxSurface(w);
-            final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
-            if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
-                mTmpUpdateAllDrawn.add(atoken);
+        final ActivityRecord activity = w.mActivityRecord;
+        if (activity != null) {
+            activity.updateLetterboxSurface(w);
+            final boolean updateAllDrawn = activity.updateDrawnWindowStates(w);
+            if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(activity)) {
+                mTmpUpdateAllDrawn.add(activity);
             }
         }
 
@@ -966,12 +966,12 @@
         return mTokenMap.get(binder);
     }
 
-    AppWindowToken getAppWindowToken(IBinder binder) {
+    ActivityRecord getActivityRecord(IBinder binder) {
         final WindowToken token = getWindowToken(binder);
         if (token == null) {
             return null;
         }
-        return token.asAppWindowToken();
+        return token.asActivityRecord();
     }
 
     private void addWindowToken(IBinder binder, WindowToken token) {
@@ -995,7 +995,7 @@
 
         mTokenMap.put(binder, token);
 
-        if (token.asAppWindowToken() == null) {
+        if (token.asActivityRecord() == null) {
             // Add non-app token to container hierarchy on the display. App tokens are added through
             // the parent container managing them (e.g. Tasks).
             switch (token.windowType) {
@@ -1015,7 +1015,7 @@
 
     WindowToken removeWindowToken(IBinder binder) {
         final WindowToken token = mTokenMap.remove(binder);
-        if (token != null && token.asAppWindowToken() == null) {
+        if (token != null && token.asActivityRecord() == null) {
             token.setExiting();
         }
         return token;
@@ -1028,7 +1028,7 @@
             return;
         }
         if (prevDc != null) {
-            if (prevDc.mTokenMap.remove(token.token) != null && token.asAppWindowToken() == null) {
+            if (prevDc.mTokenMap.remove(token.token) != null && token.asActivityRecord() == null) {
                 // Removed the token from the map, but made sure it's not an app token before
                 // removing from parent.
                 token.getParent().removeChild(token);
@@ -1057,14 +1057,14 @@
             return;
         }
 
-        final AppWindowToken appToken = token.asAppWindowToken();
+        final ActivityRecord activity = token.asActivityRecord();
 
-        if (appToken == null) {
+        if (activity == null) {
             Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token);
             return;
         }
 
-        appToken.onRemovedFromDisplay();
+        activity.onRemovedFromDisplay();
     }
 
     @Override
@@ -1255,9 +1255,9 @@
             // If we changed the orientation but mOrientationChangeComplete is already true,
             // we used seamless rotation, and we don't need to freeze the screen.
             if (freezeDisplayToken != null && !mWmService.mRoot.mOrientationChangeComplete) {
-                final AppWindowToken atoken = getAppWindowToken(freezeDisplayToken);
-                if (atoken != null) {
-                    atoken.startFreezingScreen();
+                final ActivityRecord activity = getActivityRecord(freezeDisplayToken);
+                if (activity != null) {
+                    activity.startFreezingScreen();
                 }
             }
             config = new Configuration();
@@ -2979,10 +2979,10 @@
     /**
      * Set the new focused app to this display.
      *
-     * @param newFocus the new focused AppWindowToken.
+     * @param newFocus the new focused {@link ActivityRecord}.
      * @return true if the focused app is changed.
      */
-    boolean setFocusedApp(AppWindowToken newFocus) {
+    boolean setFocusedApp(ActivityRecord newFocus) {
         if (newFocus != null) {
             final DisplayContent appDisplay = newFocus.getDisplayContent();
             if (appDisplay != this) {
@@ -3050,10 +3050,10 @@
                 wsa.destroySurface();
                 mWmService.mForceRemoves.add(w);
                 mTmpWindow = w;
-            } else if (w.mAppToken != null && w.mAppToken.isClientHidden()) {
+            } else if (w.mActivityRecord != null && w.mActivityRecord.isClientHidden()) {
                 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
                         + w + " surface=" + wsa.mSurfaceController
-                        + " token=" + w.mAppToken);
+                        + " token=" + w.mActivityRecord);
                 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE LEAK DESTROY: %s", w);
                 wsa.destroySurface();
                 mTmpWindow = w;
@@ -3122,9 +3122,9 @@
         // to be on top of it, but it is not -really- where input will go. So look down below
         // for a real window to target...
         if (target != null && target.mAttrs.type == TYPE_APPLICATION_STARTING) {
-            final AppWindowToken token = target.mAppToken;
-            if (token != null) {
-                final WindowState betterTarget = token.getImeTargetBelowWindow(target);
+            final ActivityRecord activity = target.mActivityRecord;
+            if (activity != null) {
+                final WindowState betterTarget = activity.getImeTargetBelowWindow(target);
                 if (betterTarget != null) {
                     target = betterTarget;
                 }
@@ -3158,15 +3158,15 @@
         }
 
         if (updateImeTarget) {
-            AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
-            if (token != null) {
+            ActivityRecord activity = curTarget == null ? null : curTarget.mActivityRecord;
+            if (activity != null) {
 
                 // Now some fun for dealing with window animations that modify the Z order. We need
                 // to look at all windows below the current target that are in this app, finding the
                 // highest visible one in layering.
                 WindowState highestTarget = null;
-                if (token.isSelfAnimating()) {
-                    highestTarget = token.getHighestAnimLayerWindow(curTarget);
+                if (activity.isSelfAnimating()) {
+                    highestTarget = activity.getHighestAnimLayerWindow(curTarget);
                 }
 
                 if (highestTarget != null) {
@@ -3194,8 +3194,8 @@
      * Calling {@link #computeImeTarget(boolean)} to update the input method target window in
      * the candidate app window token if needed.
      */
-    void computeImeTargetIfNeeded(AppWindowToken candidate) {
-        if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == candidate) {
+    void computeImeTargetIfNeeded(ActivityRecord candidate) {
+        if (mInputMethodTarget != null && mInputMethodTarget.mActivityRecord == candidate) {
             computeImeTarget(true /* updateImeTarget */);
         }
     }
@@ -3233,12 +3233,12 @@
         // Attach it to app if the target is part of an app and such app is covering the entire
         // screen. If it's not covering the entire screen the IME might extend beyond the apps
         // bounds.
-        if (mInputMethodTarget != null && mInputMethodTarget.mAppToken != null
+        if (mInputMethodTarget != null && mInputMethodTarget.mActivityRecord != null
                 && mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
                 // An activity with override bounds should be letterboxed inside its parent bounds,
                 // so it doesn't fill the screen.
-                && mInputMethodTarget.mAppToken.matchParentBounds()) {
-            return mInputMethodTarget.mAppToken.getSurfaceControl();
+                && mInputMethodTarget.mActivityRecord.matchParentBounds()) {
+            return mInputMethodTarget.mActivityRecord.getSurfaceControl();
         }
 
         // Otherwise, we just attach it to the display.
@@ -3341,7 +3341,7 @@
             boolean subtle) {
         final WindowManagerPolicy policy = mWmService.mPolicy;
         forAllWindows(w -> {
-            if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w)
+            if (w.mActivityRecord == null && policy.canBeHiddenByKeyguardLw(w)
                     && w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) {
                 w.startAnimation(policy.createHiddenByKeyguardExit(
                         onWallpaper, goingToShade, subtle));
@@ -3601,10 +3601,10 @@
         }
 
         while (!mTmpUpdateAllDrawn.isEmpty()) {
-            final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast();
+            final ActivityRecord activity = mTmpUpdateAllDrawn.removeLast();
             // See if any windows have been drawn, so they (and others associated with them)
             // can now be shown.
-            atoken.updateAllDrawn();
+            activity.updateAllDrawn();
         }
     }
 
@@ -4175,15 +4175,15 @@
 
         private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
                 boolean traverseTopToBottom) {
-            // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the
+            // For legacy reasons we process the TaskStack.mExitingActivities first here before the
             // app tokens.
             // TODO: Investigate if we need to continue to do this or if we can just process them
             // in-order.
             if (traverseTopToBottom) {
                 for (int i = mChildren.size() - 1; i >= 0; --i) {
-                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
-                    for (int j = appTokens.size() - 1; j >= 0; --j) {
-                        if (appTokens.get(j).forAllWindowsUnchecked(callback,
+                    final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+                    for (int j = activities.size() - 1; j >= 0; --j) {
+                        if (activities.get(j).forAllWindowsUnchecked(callback,
                                 traverseTopToBottom)) {
                             return true;
                         }
@@ -4192,10 +4192,10 @@
             } else {
                 final int count = mChildren.size();
                 for (int i = 0; i < count; ++i) {
-                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
-                    final int appTokensCount = appTokens.size();
+                    final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+                    final int appTokensCount = activities.size();
                     for (int j = 0; j < appTokensCount; j++) {
-                        if (appTokens.get(j).forAllWindowsUnchecked(callback,
+                        if (activities.get(j).forAllWindowsUnchecked(callback,
                                 traverseTopToBottom)) {
                             return true;
                         }
@@ -4207,27 +4207,27 @@
 
         void setExitingTokensHasVisible(boolean hasVisible) {
             for (int i = mChildren.size() - 1; i >= 0; --i) {
-                final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
-                for (int j = appTokens.size() - 1; j >= 0; --j) {
-                    appTokens.get(j).hasVisible = hasVisible;
+                final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+                for (int j = activities.size() - 1; j >= 0; --j) {
+                    activities.get(j).hasVisible = hasVisible;
                 }
             }
         }
 
         void removeExistingAppTokensIfPossible() {
             for (int i = mChildren.size() - 1; i >= 0; --i) {
-                final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
-                for (int j = appTokens.size() - 1; j >= 0; --j) {
-                    final AppWindowToken token = appTokens.get(j);
-                    if (!token.hasVisible && !mClosingApps.contains(token)
-                            && (!token.mIsExiting || token.isEmpty())) {
-                        // Make sure there is no animation running on this token, so any windows
+                final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+                for (int j = activities.size() - 1; j >= 0; --j) {
+                    final ActivityRecord activity = activities.get(j);
+                    if (!activity.hasVisible && !mClosingApps.contains(activity)
+                            && (!activity.mIsExiting || activity.isEmpty())) {
+                        // Make sure there is no animation running on this activity, so any windows
                         // associated with it will be removed as soon as their animations are
                         // complete.
                         cancelAnimation();
                         ProtoLog.v(WM_DEBUG_ADD_REMOVE,
-                                "performLayout: App token exiting now removed %s", token);
-                        token.removeIfPossible();
+                                "performLayout: Activity exiting now removed %s", activity);
+                        activity.removeIfPossible();
                     }
                 }
             }
@@ -4642,7 +4642,7 @@
         // Keep IME window in mAboveAppWindowsContainers as long as app's starting window exists
         // so it get's layered above the starting window.
         if (imeTarget != null
-                && !(imeTarget.mAppToken != null && imeTarget.mAppToken.hasStartingWindow())
+                && !(imeTarget.mActivityRecord != null && imeTarget.mActivityRecord.hasStartingWindow())
                 && (!(imeTarget.inSplitScreenWindowingMode() || imeTarget.mToken.isAppAnimating())
                 && (imeTarget.getSurfaceControl() != null))) {
             mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 150ae79..56bbc05 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -196,6 +196,11 @@
     // Nav bar is never forced opaque.
     private static final int NAV_BAR_FORCE_TRANSPARENT = 2;
 
+    /** Don't apply window animation (see {@link #selectAnimation}). */
+    static final int ANIMATION_NONE = -1;
+    /** Use the transit animation in style resource (see {@link #selectAnimation}). */
+    static final int ANIMATION_STYLEABLE = 0;
+
     /**
      * These are the system UI flags that, when changing, can cause the layout
      * of the screen to change.
@@ -1036,9 +1041,9 @@
     }
 
     /**
-     * Control the animation to run when a window's state changes.  Return a
-     * non-0 number to force the animation to a specific resource ID, or 0
-     * to use the default animation.
+     * Control the animation to run when a window's state changes.  Return a positive number to
+     * force the animation to a specific resource ID, {@link #ANIMATION_STYLEABLE} to use the
+     * style resource defining the animation, or {@link #ANIMATION_NONE} for no animation.
      *
      * @param win The window that is changing.
      * @param transit What is happening to the window:
@@ -1047,9 +1052,9 @@
      *                {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_SHOW}, or
      *                {@link com.android.server.policy.WindowManagerPolicy#TRANSIT_HIDE}.
      *
-     * @return Resource ID of the actual animation to use, or 0 for none.
+     * @return Resource ID of the actual animation to use, or {@link #ANIMATION_NONE} for none.
      */
-    public int selectAnimationLw(WindowState win, int transit) {
+    int selectAnimation(WindowState win, int transit) {
         if (DEBUG_ANIM) Slog.i(TAG, "selectAnimation in " + win
                 + ": transit=" + transit);
         if (win == mStatusBar) {
@@ -1057,7 +1062,7 @@
             final boolean expanded = win.getAttrs().height == MATCH_PARENT
                     && win.getAttrs().width == MATCH_PARENT;
             if (isKeyguard || expanded) {
-                return -1;
+                return ANIMATION_NONE;
             }
             if (transit == TRANSIT_EXIT
                     || transit == TRANSIT_HIDE) {
@@ -1068,7 +1073,7 @@
             }
         } else if (win == mNavigationBar) {
             if (win.getAttrs().windowAnimations != 0) {
-                return 0;
+                return ANIMATION_STYLEABLE;
             }
             // This can be on either the bottom or the right or the left.
             if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
@@ -1101,7 +1106,7 @@
                 }
             }
         } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
-            return selectDockedDividerAnimationLw(win, transit);
+            return selectDockedDividerAnimation(win, transit);
         }
 
         if (transit == TRANSIT_PREVIEW_DONE) {
@@ -1115,13 +1120,13 @@
             // is shown.  We don't want an animation on the dream, because
             // we need it shown immediately with the keyguard animating away
             // to reveal it.
-            return -1;
+            return ANIMATION_NONE;
         }
 
-        return 0;
+        return ANIMATION_STYLEABLE;
     }
 
-    private int selectDockedDividerAnimationLw(WindowState win, int transit) {
+    private int selectDockedDividerAnimation(WindowState win, int transit) {
         int insets = mDisplayContent.getDockedDividerController().getContentInsets();
 
         // If the divider is behind the navigation bar, don't animate.
@@ -1140,14 +1145,14 @@
                 || frame.bottom + insets >= win.getDisplayFrameLw().bottom);
         final boolean offscreen = offscreenLandscape || offscreenPortrait;
         if (behindNavBar || offscreen) {
-            return 0;
+            return ANIMATION_STYLEABLE;
         }
         if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
             return R.anim.fade_in;
         } else if (transit == TRANSIT_EXIT) {
             return R.anim.fade_out;
         } else {
-            return 0;
+            return ANIMATION_STYLEABLE;
         }
     }
 
@@ -2530,7 +2535,6 @@
                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
                     }
                 } else if (topIsFullscreen
-                        && !mDisplayContent.isStackVisible(WINDOWING_MODE_FREEFORM)
                         && !mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
                     if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
                     if (mStatusBarController.setBarShowingLw(false)) {
@@ -2590,7 +2594,7 @@
      *         window.
      */
     private boolean topAppHidesStatusBar() {
-        if (mTopFullscreenOpaqueWindowState == null) {
+        if (mTopFullscreenOpaqueWindowState == null || mForceShowSystemBars) {
             return false;
         }
         final int fl = PolicyControl.getWindowFlags(null,
@@ -3253,9 +3257,9 @@
         final boolean resizing = mDisplayContent.getDockedDividerController().isResizing();
 
         // We need to force system bars when the docked stack is visible, when the freeform stack
-        // is visible but also when we are resizing for the transitions when docked stack
+        // is focused but also when we are resizing for the transitions when docked stack
         // visibility changes.
-        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing
+        mForceShowSystemBars = dockedStackVisible || win.inFreeformWindowingMode() || resizing
                 || mForceShowSystemBarsFromExternal;
         final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
 
@@ -3702,7 +3706,7 @@
     @VisibleForTesting
     static boolean isOverlappingWithNavBar(WindowState targetWindow, WindowState navBarWindow) {
         if (navBarWindow == null || !navBarWindow.isVisibleLw()
-                || targetWindow.mAppToken == null || !targetWindow.isVisibleLw()) {
+                || targetWindow.mActivityRecord == null || !targetWindow.isVisibleLw()) {
             return false;
         }
 
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 414e496..67f1d1b 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -520,7 +520,7 @@
 
         // If the bounds of activity window is different from its parent, then reject to be seamless
         // because the window position may change after rotation that will look like a sudden jump.
-        if (w.mAppToken != null && !w.mAppToken.matchParentBounds()) {
+        if (w.mActivityRecord != null && !w.mActivityRecord.matchParentBounds()) {
             return false;
         }
 
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index d3e42901..b454922 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -660,7 +660,7 @@
         checkMinimizeChanged(false /* animate */);
     }
 
-    void notifyAppTransitionStarting(ArraySet<AppWindowToken> openingApps, int appTransition) {
+    void notifyAppTransitionStarting(ArraySet<ActivityRecord> openingApps, int appTransition) {
         final boolean wasMinimized = mMinimizedDock;
         checkMinimizeChanged(true /* animate */);
 
@@ -685,10 +685,10 @@
     /**
      * @return true if {@param apps} contains an activity in the docked stack, false otherwise.
      */
-    private boolean containsAppInDockedStack(ArraySet<AppWindowToken> apps) {
+    private boolean containsAppInDockedStack(ArraySet<ActivityRecord> apps) {
         for (int i = apps.size() - 1; i >= 0; i--) {
-            final AppWindowToken token = apps.valueAt(i);
-            if (token.getTask() != null && token.inSplitScreenPrimaryWindowingMode()) {
+            final ActivityRecord activity = apps.valueAt(i);
+            if (activity.getTask() != null && activity.inSplitScreenPrimaryWindowingMode()) {
                 return true;
             }
         }
@@ -722,7 +722,7 @@
         final RecentsAnimationController recentsAnim = mService.getRecentsAnimationController();
         final boolean minimizedForRecentsAnimation = recentsAnim != null &&
                 recentsAnim.isSplitScreenMinimized();
-        boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
+        boolean homeVisible = homeTask.getTopVisibleActivity() != null;
         if (homeVisible && topSecondaryStack != null) {
             // Home should only be considered visible if it is greater or equal to the top secondary
             // stack in terms of z-order.
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index abd7222..255ef6e 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -427,8 +427,8 @@
     private boolean targetWindowSupportsGlobalDrag(WindowState targetWin) {
         // Global drags are limited to system windows, and windows for apps that are targeting N and
         // above.
-        return targetWin.mAppToken == null
-                || targetWin.mAppToken.mTargetSdk >= Build.VERSION_CODES.N;
+        return targetWin.mActivityRecord == null
+                || targetWin.mActivityRecord.mTargetSdk >= Build.VERSION_CODES.N;
     }
 
     /* helper - send a ACTION_DRAG_STARTED event only if the window has not
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 7e085f6..bc95481 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -25,7 +25,7 @@
  */
 class ImeInsetsSourceProvider extends InsetsSourceProvider {
 
-    private WindowState mCurImeTarget;
+    private WindowState mImeTargetFromIme;
     private Runnable mShowImeRunner;
     private boolean mIsImeLayoutDrawn;
 
@@ -40,8 +40,8 @@
     void onPostLayout() {
         super.onPostLayout();
 
-        if (mCurImeTarget != null
-                && mCurImeTarget == mDisplayContent.mInputMethodTarget
+        if (mImeTargetFromIme != null
+                && isImeTargetFromDisplayContentAndImeSame()
                 && mWin != null
                 && mWin.isDrawnLw()
                 && !mWin.mGivenInsetsPending) {
@@ -64,18 +64,33 @@
     /**
      * Called from {@link WindowManagerInternal#showImePostLayout} when {@link InputMethodService}
      * requests to show IME on {@param imeTarget}.
-     * @param imeTarget imeTarget on which IME is displayed.
+     * @param imeTarget imeTarget on which IME request is coming from.
      */
     void scheduleShowImePostLayout(WindowState imeTarget) {
-        mCurImeTarget = imeTarget;
+        mImeTargetFromIme = imeTarget;
         mShowImeRunner = () -> {
             // Target should still be the same.
-            if (mCurImeTarget == mDisplayContent.mInputMethodTarget) {
+            if (isImeTargetFromDisplayContentAndImeSame()) {
                 mDisplayContent.mInputMethodTarget.showInsets(
                         WindowInsets.Type.ime(), true /* fromIme */);
             }
-            mCurImeTarget = null;
+            mImeTargetFromIme = null;
         };
     }
 
+    private boolean isImeTargetFromDisplayContentAndImeSame() {
+        // IMMS#mLastImeTargetWindow always considers focused window as
+        // IME target, however DisplayContent#computeImeTarget() can compute
+        // a different IME target.
+        // Refer to WindowManagerService#applyImeVisibility(token, false).
+        // If IMMS's imeTarget is child of DisplayContent's imeTarget and child window
+        // is above the parent, we will consider it as the same target for now.
+        // TODO(b/139861270): Remove the child & sublayer check once IMMS is aware of
+        //  actual IME target.
+        return mImeTargetFromIme == mDisplayContent.mInputMethodTarget
+                || (mDisplayContent.mInputMethodTarget.getParentWindow() == mImeTargetFromIme
+                        && mDisplayContent.mInputMethodTarget.mSubLayer
+                                > mImeTargetFromIme.mSubLayer);
+    }
+
 }
diff --git a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
index d774dc3..82ac6b8 100644
--- a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
@@ -189,7 +189,7 @@
                         | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
                         | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                 PixelFormat.TRANSLUCENT);
-        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+        lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         lp.setTitle("ImmersiveModeConfirmation");
         lp.windowAnimations = com.android.internal.R.style.Animation_ImmersiveModeConfirmation;
         lp.token = getWindowToken();
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index eb9b3e9..7f9e76b 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -81,7 +81,7 @@
      */
     @Override
     public long notifyANR(IBinder token, String reason) {
-        AppWindowToken appWindowToken = null;
+        ActivityRecord activity = null;
         WindowState windowState = null;
         boolean aboveSystem = false;
         //TODO(b/141764879) Limit scope of wm lock when input calls notifyANR
@@ -89,7 +89,7 @@
             if (token != null) {
                 windowState = mService.mInputToWindowMap.get(token);
                 if (windowState != null) {
-                    appWindowToken = windowState.mAppToken;
+                    activity = windowState.mActivityRecord;
                 }
             }
 
@@ -103,30 +103,30 @@
                 int systemAlertLayer = mService.mPolicy.getWindowLayerFromTypeLw(
                         TYPE_APPLICATION_OVERLAY, windowState.mOwnerCanAddInternalSystemWindow);
                 aboveSystem = windowState.mBaseLayer > systemAlertLayer;
-            } else if (appWindowToken != null) {
+            } else if (activity != null) {
                 Slog.i(TAG_WM, "Input event dispatching timed out "
-                        + "sending to application " + appWindowToken.stringName
+                        + "sending to application " + activity.stringName
                         + ".  Reason: " + reason);
             } else {
                 Slog.i(TAG_WM, "Input event dispatching timed out "
                         + ".  Reason: " + reason);
             }
 
-            mService.saveANRStateLocked(appWindowToken, windowState, reason);
+            mService.saveANRStateLocked(activity, windowState, reason);
         }
 
         // All the calls below need to happen without the WM lock held since they call into AM.
         mService.mAtmInternal.saveANRState(reason);
 
-        if (appWindowToken != null && appWindowToken.appToken != null) {
+        if (activity != null && activity.appToken != null) {
             // Notify the activity manager about the timeout and let it decide whether
             // to abort dispatching or keep waiting.
-            final boolean abort = appWindowToken.keyDispatchingTimedOut(reason,
+            final boolean abort = activity.keyDispatchingTimedOut(reason,
                     windowState.mSession.mPid);
             if (!abort) {
                 // The activity manager declined to abort dispatching.
                 // Wait a bit longer and timeout again later.
-                return appWindowToken.mInputDispatchingTimeoutNanos;
+                return activity.mInputDispatchingTimeoutNanos;
             }
         } else if (windowState != null) {
             // Notify the activity manager about the timeout and let it decide whether
@@ -266,7 +266,8 @@
 
         final IWindow focusedWindow = mFocusedWindow.get();
         if (focusedWindow != null) {
-            if (focusedWindow.asBinder() == newFocusedWindow.asBinder()) {
+            if (newFocusedWindow != null
+                    && newFocusedWindow.asBinder() == focusedWindow.asBinder()) {
                 Slog.w(TAG, "notifyFocusChanged called with unchanged mFocusedWindow="
                         + focusedWindow);
                 return false;
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index dc9a598..f9ff2e3 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -112,7 +112,7 @@
         }
     }
 
-    private final Runnable mUpdateInputWindows = new Runnable() {
+    private class UpdateInputWindows implements Runnable {
         @Override
         public void run() {
             synchronized (mService.mGlobalLock) {
@@ -148,7 +148,9 @@
                 mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);
             }
         }
-    };
+    }
+
+    private final UpdateInputWindows mUpdateInputWindows = new UpdateInputWindows();
 
     public InputMonitor(WindowManagerService service, int displayId) {
         mService = service;
@@ -261,7 +263,7 @@
         inputWindowHandle.canReceiveKeys = child.canReceiveKeys();
         inputWindowHandle.hasFocus = hasFocus;
         inputWindowHandle.hasWallpaper = hasWallpaper;
-        inputWindowHandle.paused = child.mAppToken != null ? child.mAppToken.paused : false;
+        inputWindowHandle.paused = child.mActivityRecord != null ? child.mActivityRecord.paused : false;
         inputWindowHandle.layer = child.mLayer;
         inputWindowHandle.ownerPid = child.mSession.mPid;
         inputWindowHandle.ownerUid = child.mSession.mUid;
@@ -351,7 +353,7 @@
         }
     }
 
-    public void setFocusedAppLw(AppWindowToken newApp) {
+    public void setFocusedAppLw(ActivityRecord newApp) {
         // Focused app has changed.
         if (newApp == null) {
             mService.mInputManager.setFocusedApplication(mDisplayId, null);
@@ -474,7 +476,7 @@
                 final RecentsAnimationController recentsAnimationController =
                         mService.getRecentsAnimationController();
                 if (recentsAnimationController != null
-                        && recentsAnimationController.shouldApplyInputConsumer(w.mAppToken)) {
+                        && recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord)) {
                     if (recentsAnimationController.updateInputConsumerForApp(
                             recentsAnimationInputConsumer.mWindowHandle, hasFocus)) {
                         recentsAnimationInputConsumer.show(mInputTransaction, w);
diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java
index b7184a5..22ba82a 100644
--- a/services/core/java/com/android/server/wm/InsetsControlTarget.java
+++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java
@@ -33,4 +33,13 @@
      */
     default void showInsets(@InsetType int types, boolean fromIme) {
     }
+
+    /**
+     * Instructs the control target to hide inset sources.
+     *
+     * @param types to specify which types of insets source window should be hidden.
+     * @param fromIme {@code true} if IME hide request originated from {@link InputMethodService}.
+     */
+    default void hideInsets(@InsetType int types, boolean fromIme) {
+    }
 }
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 2b5eb3a..52cc422 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -16,7 +16,7 @@
 
 package com.android.server.wm;
 
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
@@ -180,7 +180,7 @@
         if (!mKeyguardShowing) {
             return;
         }
-        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway");
+        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "keyguardGoingAway");
         mService.deferWindowLayout();
         try {
             setKeyguardGoingAway(true);
@@ -202,11 +202,8 @@
                     true /* taskSwitch */);
             mWindowManager.executeAppTransition();
         } finally {
-            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway: surfaceLayout");
             mService.continueWindowLayout();
-            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
-
-            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java b/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java
index 93e2d8d..362ed3c 100644
--- a/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java
+++ b/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java
@@ -70,9 +70,12 @@
     }
 
     @Override
-    public void onIntentStarted(Intent intent) {
+    public void onIntentStarted(Intent intent, long timestampNs) {
         mHandler.sendMessage(PooledLambda.obtainMessage(
-                LaunchObserverRegistryImpl::handleOnIntentStarted, this, intent));
+                LaunchObserverRegistryImpl::handleOnIntentStarted,
+                this,
+                intent,
+                timestampNs));
     }
 
     @Override
@@ -99,9 +102,22 @@
 
     @Override
     public void onActivityLaunchFinished(
-        @ActivityRecordProto byte[] activity) {
+        @ActivityRecordProto byte[] activity,
+        long timestampNs) {
         mHandler.sendMessage(PooledLambda.obtainMessage(
-                LaunchObserverRegistryImpl::handleOnActivityLaunchFinished, this, activity));
+            LaunchObserverRegistryImpl::handleOnActivityLaunchFinished,
+            this,
+            activity,
+            timestampNs));
+    }
+
+    @Override
+    public void onReportFullyDrawn(@ActivityRecordProto byte[] activity, long timestampNs) {
+        mHandler.sendMessage(PooledLambda.obtainMessage(
+            LaunchObserverRegistryImpl::handleOnReportFullyDrawn,
+            this,
+            activity,
+            timestampNs));
     }
 
     // Use PooledLambda.obtainMessage to invoke below methods. Every method reference must be
@@ -116,11 +132,11 @@
         mList.remove(observer);
     }
 
-    private void handleOnIntentStarted(Intent intent) {
+    private void handleOnIntentStarted(Intent intent, long timestampNs) {
         // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
         for (int i = 0; i < mList.size(); i++) {
              ActivityMetricsLaunchObserver o = mList.get(i);
-             o.onIntentStarted(intent);
+             o.onIntentStarted(intent, timestampNs);
         }
     }
 
@@ -152,11 +168,20 @@
     }
 
     private void handleOnActivityLaunchFinished(
-            @ActivityRecordProto byte[] activity) {
+            @ActivityRecordProto byte[] activity, long timestampNs) {
         // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
         for (int i = 0; i < mList.size(); i++) {
             ActivityMetricsLaunchObserver o = mList.get(i);
-            o.onActivityLaunchFinished(activity);
+            o.onActivityLaunchFinished(activity, timestampNs);
+        }
+    }
+
+    private void handleOnReportFullyDrawn(
+            @ActivityRecordProto byte[] activity, long timestampNs) {
+        // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
+        for (int i = 0; i < mList.size(); i++) {
+            ActivityMetricsLaunchObserver o = mList.get(i);
+            o.onReportFullyDrawn(activity, timestampNs);
         }
     }
 }
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index c59a73b..6721ef8 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -174,7 +174,7 @@
 
         InputInterceptor(String namePrefix, WindowState win) {
             mWmService = win.mWmService;
-            final String name = namePrefix + (win.mAppToken != null ? win.mAppToken : win);
+            final String name = namePrefix + (win.mActivityRecord != null ? win.mActivityRecord : win);
             final InputChannel[] channels = InputChannel.openInputChannelPair(name);
             mServerChannel = channels[0];
             mClientChannel = channels[1];
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 062cdc5..12579e6 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -22,7 +22,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.WindowManager.TRANSIT_NONE;
 
 import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
@@ -158,7 +158,7 @@
 
     void startRecentsActivity(IRecentsAnimationRunner recentsAnimationRunner) {
         ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "startRecentsActivity(): intent=%s", mTargetIntent);
-        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "RecentsAnimation#startRecentsActivity");
+        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "RecentsAnimation#startRecentsActivity");
 
         // TODO(multi-display) currently only support recents animation in default display.
         final DisplayContent dc =
@@ -263,7 +263,7 @@
             throw e;
         } finally {
             mService.continueWindowLayout();
-            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         }
     }
 
@@ -297,7 +297,7 @@
             }
 
             mWindowManager.inSurfaceTransaction(() -> {
-                Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER,
+                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                         "RecentsAnimation#onAnimationFinished_inSurfaceTransaction");
                 mService.deferWindowLayout();
                 try {
@@ -394,7 +394,7 @@
                     throw e;
                 } finally {
                     mService.continueWindowLayout();
-                    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                    Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                 }
             });
         }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index bd27905..9a58a68 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -98,11 +98,13 @@
     private final ArrayList<WallpaperAnimationAdapter> mPendingWallpaperAnimations =
             new ArrayList<>();
     private final int mDisplayId;
-    private final Runnable mFailsafeRunnable = () ->
-            cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "failSafeRunnable");
+    private boolean mWillFinishToHome = false;
+    private final Runnable mFailsafeRunnable = () -> cancelAnimation(
+            mWillFinishToHome ? REORDER_MOVE_TO_TOP : REORDER_MOVE_TO_ORIGINAL_POSITION,
+            "failSafeRunnable");
 
     // The recents component app token that is shown behind the visibile tasks
-    private AppWindowToken mTargetAppToken;
+    private ActivityRecord mTargetActivityRecord;
     private DisplayContent mDisplayContent;
     private int mTargetActivityType;
     private Rect mMinimizedHomeBounds = new Rect();
@@ -326,6 +328,13 @@
                 }
             }
         }
+
+        @Override
+        public void setWillFinishToHome(boolean willFinishToHome) {
+            synchronized (mService.getWindowManagerLock()) {
+                mWillFinishToHome = willFinishToHome;
+            }
+        }
     };
 
     /**
@@ -391,13 +400,13 @@
         }
 
         // Adjust the wallpaper visibility for the showing target activity
-        final AppWindowToken recentsComponentAppToken =
-                targetStack.getTopChild().getTopFullscreenAppToken();
-        if (recentsComponentAppToken != null) {
+        final ActivityRecord recentsComponentActivity =
+                targetStack.getTopChild().getTopFullscreenActivity();
+        if (recentsComponentActivity != null) {
             ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
-                    "setHomeApp(%s)", recentsComponentAppToken.getName());
-            mTargetAppToken = recentsComponentAppToken;
-            if (recentsComponentAppToken.windowsCanBeWallpaperTarget()) {
+                    "setHomeApp(%s)", recentsComponentActivity.getName());
+            mTargetActivityRecord = recentsComponentActivity;
+            if (recentsComponentActivity.windowsCanBeWallpaperTarget()) {
                 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
                 mDisplayContent.setLayoutNeeded();
             }
@@ -471,13 +480,13 @@
             // insets for the target app window after a rotation
             mDisplayContent.performLayout(false /* initial */, false /* updateInputWindows */);
 
-            final Rect minimizedHomeBounds = mTargetAppToken != null
-                    && mTargetAppToken.inSplitScreenSecondaryWindowingMode()
+            final Rect minimizedHomeBounds = mTargetActivityRecord != null
+                    && mTargetActivityRecord.inSplitScreenSecondaryWindowingMode()
                             ? mMinimizedHomeBounds
                             : null;
             final Rect contentInsets;
-            if (mTargetAppToken != null && mTargetAppToken.findMainWindow() != null) {
-                contentInsets = mTargetAppToken.findMainWindow().getContentInsets();
+            if (mTargetActivityRecord != null && mTargetActivityRecord.findMainWindow() != null) {
+                contentInsets = mTargetActivityRecord.findMainWindow().getContentInsets();
             } else {
                 // If the window for the activity had not yet been created, use the display insets.
                 mService.getStableInsets(mDisplayId, mTmpRect);
@@ -494,7 +503,8 @@
         }
         final SparseIntArray reasons = new SparseIntArray();
         reasons.put(WINDOWING_MODE_FULLSCREEN, APP_TRANSITION_RECENTS_ANIM);
-        mService.mAtmInternal.notifyAppTransitionStarting(reasons, SystemClock.uptimeMillis());
+        mService.mAtmInternal
+            .notifyAppTransitionStarting(reasons, SystemClock.elapsedRealtimeNanos());
     }
 
     private RemoteAnimationTarget[] createAppAnimations() {
@@ -672,10 +682,10 @@
 
         // We have deferred all notifications to the target app as a part of the recents animation,
         // so if we are actually transitioning there, notify again here
-        if (mTargetAppToken != null) {
+        if (mTargetActivityRecord != null) {
             if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) {
                 mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(
-                        mTargetAppToken.token);
+                        mTargetActivityRecord.token);
             }
         }
 
@@ -730,25 +740,26 @@
     }
 
     boolean isWallpaperVisible(WindowState w) {
-        return w != null && w.mAttrs.type == TYPE_BASE_APPLICATION && w.mAppToken != null
-                && mTargetAppToken == w.mAppToken && isTargetOverWallpaper();
+        return w != null && w.mAttrs.type == TYPE_BASE_APPLICATION && w.mActivityRecord != null
+                && mTargetActivityRecord == w.mActivityRecord && isTargetOverWallpaper();
     }
 
     /**
      * @return Whether to use the input consumer to override app input to route home/recents.
      */
-    boolean shouldApplyInputConsumer(AppWindowToken appToken) {
+    boolean shouldApplyInputConsumer(ActivityRecord activity) {
         // Only apply the input consumer if it is enabled, it is not the target (home/recents)
         // being revealed with the transition, and we are actively animating the app as a part of
         // the animation
-        return mInputConsumerEnabled && mTargetAppToken != appToken && isAnimatingApp(appToken);
+        return mInputConsumerEnabled && mTargetActivityRecord != activity
+                && isAnimatingApp(activity);
     }
 
     boolean updateInputConsumerForApp(InputWindowHandle inputWindowHandle,
             boolean hasFocus) {
         // Update the input consumer touchable region to match the target app main window
-        final WindowState targetAppMainWindow = mTargetAppToken != null
-                ? mTargetAppToken.findMainWindow()
+        final WindowState targetAppMainWindow = mTargetActivityRecord != null
+                ? mTargetActivityRecord.findMainWindow()
                 : null;
         if (targetAppMainWindow != null) {
             targetAppMainWindow.getBounds(mTmpRect);
@@ -759,15 +770,15 @@
         return false;
     }
 
-    boolean isTargetApp(AppWindowToken token) {
-        return mTargetAppToken != null && token == mTargetAppToken;
+    boolean isTargetApp(ActivityRecord activity) {
+        return mTargetActivityRecord != null && activity == mTargetActivityRecord;
     }
 
     private boolean isTargetOverWallpaper() {
-        if (mTargetAppToken == null) {
+        if (mTargetActivityRecord == null) {
             return false;
         }
-        return mTargetAppToken.windowsCanBeWallpaperTarget();
+        return mTargetActivityRecord.windowsCanBeWallpaperTarget();
     }
 
     boolean isAnimatingTask(Task task) {
@@ -788,12 +799,12 @@
         return false;
     }
 
-    private boolean isAnimatingApp(AppWindowToken appToken) {
+    private boolean isAnimatingApp(ActivityRecord activity) {
         for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
             final Task task = mPendingAnimations.get(i).mTask;
             for (int j = task.getChildCount() - 1; j >= 0; j--) {
-                final AppWindowToken app = task.getChildAt(j);
-                if (app == appToken) {
+                final ActivityRecord app = task.getChildAt(j);
+                if (app == activity) {
                     return true;
                 }
             }
@@ -803,7 +814,7 @@
 
     boolean shouldIgnoreForAccessibility(WindowState windowState) {
         final Task task = windowState.getTask();
-        return task != null && isAnimatingTask(task) && !isTargetApp(windowState.mAppToken);
+        return task != null && isAnimatingTask(task) && !isTargetApp(windowState.mActivityRecord);
     }
 
     @VisibleForTesting
@@ -826,7 +837,7 @@
         }
 
         RemoteAnimationTarget createRemoteAnimationTarget() {
-            final AppWindowToken topApp = mTask.getTopVisibleAppToken();
+            final ActivityRecord topApp = mTask.getTopVisibleActivity();
             final WindowState mainWindow = topApp != null
                     ? topApp.findMainWindow()
                     : null;
@@ -835,7 +846,7 @@
             }
             final Rect insets = new Rect();
             mainWindow.getContentInsets(insets);
-            InsetUtils.addInsets(insets, mainWindow.mAppToken.getLetterboxInsets());
+            InsetUtils.addInsets(insets, mainWindow.mActivityRecord.getLetterboxInsets());
             final int mode = topApp.getActivityType() == mTargetActivityType
                     ? MODE_OPENING
                     : MODE_CLOSING;
@@ -913,7 +924,7 @@
         pw.print(innerPrefix); pw.println("mCanceled=" + mCanceled);
         pw.print(innerPrefix); pw.println("mInputConsumerEnabled=" + mInputConsumerEnabled);
         pw.print(innerPrefix); pw.println("mSplitScreenMinimized=" + mSplitScreenMinimized);
-        pw.print(innerPrefix); pw.println("mTargetAppToken=" + mTargetAppToken);
+        pw.print(innerPrefix); pw.println("mTargetActivityRecord=" + mTargetActivityRecord);
         pw.print(innerPrefix); pw.println("isTargetOverWallpaper=" + isTargetOverWallpaper());
         pw.print(innerPrefix); pw.println("mRequestDeferCancelUntilNextTransition="
                 + mRequestDeferCancelUntilNextTransition);
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 2b2ae92..c23ffd9 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -76,20 +76,20 @@
     }
 
     /**
-     * Creates an animation record for each individual {@link AppWindowToken}.
+     * Creates an animation record for each individual {@link ActivityRecord}.
      *
-     * @param appWindowToken The app to animate.
+     * @param activity The app to animate.
      * @param position The position app bounds, in screen coordinates.
      * @param stackBounds The stack bounds of the app relative to position.
      * @param startBounds The stack bounds before the transition, in screen coordinates
      * @return The record representing animation(s) to run on the app.
      */
-    RemoteAnimationRecord createRemoteAnimationRecord(AppWindowToken appWindowToken,
-            Point position, Rect stackBounds, Rect startBounds) {
+    RemoteAnimationRecord createRemoteAnimationRecord(ActivityRecord activity, Point position,
+            Rect stackBounds, Rect startBounds) {
         ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createAnimationAdapter(): token=%s",
-                appWindowToken);
+                activity);
         final RemoteAnimationRecord adapters =
-                new RemoteAnimationRecord(appWindowToken, position, stackBounds, startBounds);
+                new RemoteAnimationRecord(activity, position, stackBounds, startBounds);
         mPendingAnimations.add(adapters);
         return adapters;
     }
@@ -169,11 +169,11 @@
             final RemoteAnimationRecord wrappers = mPendingAnimations.get(i);
             final RemoteAnimationTarget target = wrappers.createRemoteAnimationTarget();
             if (target != null) {
-                ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tAdd token=%s", wrappers.mAppWindowToken);
+                ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tAdd token=%s", wrappers.mActivityRecord);
                 targets.add(target);
             } else {
                 ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tRemove token=%s",
-                        wrappers.mAppWindowToken);
+                        wrappers.mActivityRecord);
 
                 // We can't really start an animation but we still need to make sure to finish the
                 // pending animation that was started by SurfaceAnimator
@@ -228,7 +228,7 @@
                                 .onAnimationFinished(adapters.mThumbnailAdapter);
                     }
                     mPendingAnimations.remove(i);
-                    ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tapp=%s", adapters.mAppWindowToken);
+                    ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tapp=%s", adapters.mActivityRecord);
                 }
 
                 for (int i = mPendingWallpaperAnimations.size() - 1; i >= 0; i--) {
@@ -345,12 +345,12 @@
         RemoteAnimationAdapterWrapper mAdapter;
         RemoteAnimationAdapterWrapper mThumbnailAdapter = null;
         RemoteAnimationTarget mTarget;
-        final AppWindowToken mAppWindowToken;
+        final ActivityRecord mActivityRecord;
         final Rect mStartBounds;
 
-        RemoteAnimationRecord(AppWindowToken appWindowToken, Point endPos, Rect endBounds,
+        RemoteAnimationRecord(ActivityRecord activityRecord, Point endPos, Rect endBounds,
                 Rect startBounds) {
-            mAppWindowToken = appWindowToken;
+            mActivityRecord = activityRecord;
             mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, endBounds);
             if (startBounds != null) {
                 mStartBounds = new Rect(startBounds);
@@ -366,8 +366,8 @@
         }
 
         RemoteAnimationTarget createRemoteAnimationTarget() {
-            final Task task = mAppWindowToken.getTask();
-            final WindowState mainWindow = mAppWindowToken.findMainWindow();
+            final Task task = mActivityRecord.getTask();
+            final WindowState mainWindow = mActivityRecord.findMainWindow();
             if (task == null || mainWindow == null || mAdapter == null
                     || mAdapter.mCapturedFinishCallback == null
                     || mAdapter.mCapturedLeash == null) {
@@ -375,11 +375,11 @@
             }
             final Rect insets = new Rect();
             mainWindow.getContentInsets(insets);
-            InsetUtils.addInsets(insets, mAppWindowToken.getLetterboxInsets());
+            InsetUtils.addInsets(insets, mActivityRecord.getLetterboxInsets());
             mTarget = new RemoteAnimationTarget(task.mTaskId, getMode(),
-                    mAdapter.mCapturedLeash, !mAppWindowToken.fillsParent(),
+                    mAdapter.mCapturedLeash, !mActivityRecord.fillsParent(),
                     mainWindow.mWinAnimator.mLastClipRect, insets,
-                    mAppWindowToken.getPrefixOrderIndex(), mAdapter.mPosition,
+                    mActivityRecord.getPrefixOrderIndex(), mAdapter.mPosition,
                     mAdapter.mStackBounds, task.getWindowConfiguration(), false /*isNotInRecents*/,
                     mThumbnailAdapter != null ? mThumbnailAdapter.mCapturedLeash : null,
                     mStartBounds);
@@ -387,10 +387,10 @@
         }
 
         private int getMode() {
-            final DisplayContent dc = mAppWindowToken.getDisplayContent();
-            if (dc.mOpeningApps.contains(mAppWindowToken)) {
+            final DisplayContent dc = mActivityRecord.getDisplayContent();
+            if (dc.mOpeningApps.contains(mActivityRecord)) {
                 return RemoteAnimationTarget.MODE_OPENING;
-            } else if (dc.mChangingApps.contains(mAppWindowToken)) {
+            } else if (dc.mChangingApps.contains(mActivityRecord)) {
                 return RemoteAnimationTarget.MODE_CHANGING;
             } else {
                 return RemoteAnimationTarget.MODE_CLOSING;
@@ -423,7 +423,7 @@
             ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation");
 
             // Restore z-layering, position and stack crop until client has a chance to modify it.
-            t.setLayer(animationLeash, mRecord.mAppWindowToken.getPrefixOrderIndex());
+            t.setLayer(animationLeash, mRecord.mActivityRecord.getPrefixOrderIndex());
             if (mRecord.mStartBounds != null) {
                 t.setPosition(animationLeash, mRecord.mStartBounds.left, mRecord.mStartBounds.top);
                 t.setWindowCrop(animationLeash, mRecord.mStartBounds.width(),
@@ -464,7 +464,7 @@
 
         @Override
         public void dump(PrintWriter pw, String prefix) {
-            pw.print(prefix); pw.print("token="); pw.println(mRecord.mAppWindowToken);
+            pw.print(prefix); pw.print("token="); pw.println(mRecord.mActivityRecord);
             if (mRecord.mTarget != null) {
                 pw.print(prefix); pw.println("Target:");
                 mRecord.mTarget.dump(pw, prefix + "  ");
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index d78d517..60833c3 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -983,7 +983,7 @@
             stack.resize(task.getRequestedOverrideBounds(), null /* tempTaskBounds */,
                     null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS, !DEFER_RESUME);
 
-            if (task.mActivities.size() == 1) {
+            if (task.getChildCount() == 1) {
                 // Defer resume until below, and do not schedule PiP changes until we animate below
                 task.reparent(stack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE, DEFER_RESUME,
                         false /* schedulePictureInPictureModeChange */, reason);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index b6a05d1..17f5abd 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -129,7 +129,7 @@
     private int mTopFocusedDisplayId = INVALID_DISPLAY;
 
     // Map from the PID to the top most app which has a focused window of the process.
-    final HashMap<Integer, AppWindowToken> mTopFocusedAppByProcess = new HashMap<>();
+    final HashMap<Integer, ActivityRecord> mTopFocusedAppByProcess = new HashMap<>();
 
     // Only a separate transaction until we separate the apply surface changes
     // transaction from the global transaction.
@@ -145,9 +145,9 @@
     };
 
     private static final Consumer<WindowState> sRemoveReplacedWindowsConsumer = w -> {
-        final AppWindowToken aToken = w.mAppToken;
-        if (aToken != null) {
-            aToken.removeReplacedWindowIfNeeded(w);
+        final ActivityRecord activity = w.mActivityRecord;
+        if (activity != null) {
+            activity.removeReplacedWindowIfNeeded(w);
         }
     };
 
@@ -175,7 +175,7 @@
             if (newFocus != null) {
                 final int pidOfNewFocus = newFocus.mSession.mPid;
                 if (mTopFocusedAppByProcess.get(pidOfNewFocus) == null) {
-                    mTopFocusedAppByProcess.put(pidOfNewFocus, newFocus.mAppToken);
+                    mTopFocusedAppByProcess.put(pidOfNewFocus, newFocus.mActivityRecord);
                 }
                 if (topFocusedDisplayId == INVALID_DISPLAY) {
                     topFocusedDisplayId = dc.getDisplayId();
@@ -330,12 +330,12 @@
      * NOTE: Only one AppWindowToken is allowed to exist in the system for a binder token, since
      * AppWindowToken represents an activity which can only exist on one display.
      */
-    AppWindowToken getAppWindowToken(IBinder binder) {
+    ActivityRecord getActivityRecord(IBinder binder) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final DisplayContent dc = mChildren.get(i);
-            final AppWindowToken atoken = dc.getAppWindowToken(binder);
-            if (atoken != null) {
-                return atoken;
+            final ActivityRecord activity = dc.getActivityRecord(binder);
+            if (activity != null) {
+                return activity;
             }
         }
         return null;
@@ -541,8 +541,8 @@
                     ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
                             "SURFACE RECOVER DESTROY: %s",  winAnimator.mWin);
                     winAnimator.destroySurface();
-                    if (winAnimator.mWin.mAppToken != null) {
-                        winAnimator.mWin.mAppToken.removeStartingWindow();
+                    if (winAnimator.mWin.mActivityRecord != null) {
+                        winAnimator.mWin.mActivityRecord.removeStartingWindow();
                     }
                 }
 
diff --git a/services/core/java/com/android/server/wm/SnapshotStartingData.java b/services/core/java/com/android/server/wm/SnapshotStartingData.java
index c9e43c5..3764122 100644
--- a/services/core/java/com/android/server/wm/SnapshotStartingData.java
+++ b/services/core/java/com/android/server/wm/SnapshotStartingData.java
@@ -35,7 +35,7 @@
     }
 
     @Override
-    StartingSurface createStartingSurface(AppWindowToken atoken) {
-        return mService.mTaskSnapshotController.createStartingSurface(atoken, mSnapshot);
+    StartingSurface createStartingSurface(ActivityRecord activity) {
+        return mService.mTaskSnapshotController.createStartingSurface(activity, mSnapshot);
     }
 }
diff --git a/services/core/java/com/android/server/wm/SplashScreenStartingData.java b/services/core/java/com/android/server/wm/SplashScreenStartingData.java
index f52ce38..726b7da 100644
--- a/services/core/java/com/android/server/wm/SplashScreenStartingData.java
+++ b/services/core/java/com/android/server/wm/SplashScreenStartingData.java
@@ -52,9 +52,9 @@
     }
 
     @Override
-    StartingSurface createStartingSurface(AppWindowToken atoken) {
-        return mService.mPolicy.addSplashScreen(atoken.token, mPkg, mTheme, mCompatInfo,
+    StartingSurface createStartingSurface(ActivityRecord activity) {
+        return mService.mPolicy.addSplashScreen(activity.token, mPkg, mTheme, mCompatInfo,
                 mNonLocalizedLabel, mLabelRes, mIcon, mLogo, mWindowFlags,
-                mMergedOverrideConfiguration, atoken.getDisplayContent().getDisplayId());
+                mMergedOverrideConfiguration, activity.getDisplayContent().getDisplayId());
     }
 }
diff --git a/services/core/java/com/android/server/wm/StartingData.java b/services/core/java/com/android/server/wm/StartingData.java
index eb5011f..2e6e777 100644
--- a/services/core/java/com/android/server/wm/StartingData.java
+++ b/services/core/java/com/android/server/wm/StartingData.java
@@ -33,9 +33,9 @@
      * Creates the actual starting window surface. DO NOT HOLD THE WINDOW MANAGER LOCK WHEN CALLING
      * THIS METHOD.
      *
-     * @param atoken the app to add the starting window to
+     * @param activity the app to add the starting window to
      * @return a class implementing {@link StartingSurface} for easy removal with
      *         {@link StartingSurface#remove}
      */
-    abstract StartingSurface createStartingSurface(AppWindowToken atoken);
-}
\ No newline at end of file
+    abstract StartingSurface createStartingSurface(ActivityRecord activity);
+}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index a181c18..1db3149f 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -58,7 +58,7 @@
 import java.io.PrintWriter;
 import java.util.function.Consumer;
 
-class Task extends WindowContainer<AppWindowToken> implements ConfigurationContainerListener{
+class Task extends WindowContainer<ActivityRecord> implements ConfigurationContainerListener{
     static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_WM;
 
     // TODO: Track parent marks like this in WindowContainer.
@@ -120,9 +120,12 @@
 
     // TODO: Remove after unification.
     @Override
-    public void onConfigurationChanged(Configuration newParentConfig) {
-        // Only forward configuration changes in cases where children won't get it from TaskRecord.
-        onConfigurationChanged(newParentConfig, mTaskRecord == null /*forwardToChildren*/);
+    public void onConfigurationChanged(Configuration newParentConfig, boolean forwardToChildren) {
+        // Forward configuration changes in cases
+        // - children won't get it from TaskRecord
+        // - it's a pinned task
+        forwardToChildren &= (mTaskRecord == null) || inPinnedWindowingMode();
+        super.onConfigurationChanged(newParentConfig, forwardToChildren);
     }
 
     Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode,
@@ -170,14 +173,14 @@
     }
 
     @Override
-    void addChild(AppWindowToken wtoken, int position) {
+    void addChild(ActivityRecord child, int position) {
         position = getAdjustedAddPosition(position);
-        super.addChild(wtoken, position);
+        super.addChild(child, position);
         mDeferRemoval = false;
     }
 
     @Override
-    void positionChildAt(int position, AppWindowToken child, boolean includingParents) {
+    void positionChildAt(int position, ActivityRecord child, boolean includingParents) {
         position = getAdjustedAddPosition(position);
         super.positionChildAt(position, child, includingParents);
         mDeferRemoval = false;
@@ -279,16 +282,16 @@
     }
 
     @Override
-    void removeChild(AppWindowToken token) {
-        if (!mChildren.contains(token)) {
+    void removeChild(ActivityRecord child) {
+        if (!mChildren.contains(child)) {
             Slog.e(TAG, "removeChild: token=" + this + " not found.");
             return;
         }
 
-        super.removeChild(token);
+        super.removeChild(child);
 
         if (mChildren.isEmpty()) {
-            EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeAppToken: last token");
+            EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeActivity: last activity");
             if (mDeferRemoval) {
                 removeIfPossible();
             }
@@ -410,7 +413,7 @@
 
     /**
      * Prepares the task bounds to be frozen with the current size. See
-     * {@link AppWindowToken#freezeBounds}.
+     * {@link ActivityRecord#freezeBounds}.
      */
     void prepareFreezingBounds() {
         mPreparedFrozenBounds.set(getBounds());
@@ -471,7 +474,7 @@
     private boolean getMaxVisibleBounds(Rect out) {
         boolean foundTop = false;
         for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final AppWindowToken token = mChildren.get(i);
+            final ActivityRecord token = mChildren.get(i);
             // skip hidden (or about to hide) apps
             if (token.mIsExiting || token.isClientHidden() || token.hiddenRequested) {
                 continue;
@@ -648,24 +651,24 @@
     }
 
     WindowState getTopVisibleAppMainWindow() {
-        final AppWindowToken token = getTopVisibleAppToken();
-        return token != null ? token.findMainWindow() : null;
+        final ActivityRecord activity = getTopVisibleActivity();
+        return activity != null ? activity.findMainWindow() : null;
     }
 
-    AppWindowToken getTopFullscreenAppToken() {
+    ActivityRecord getTopFullscreenActivity() {
         for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final AppWindowToken token = mChildren.get(i);
-            final WindowState win = token.findMainWindow();
+            final ActivityRecord activity = mChildren.get(i);
+            final WindowState win = activity.findMainWindow();
             if (win != null && win.mAttrs.isFullscreen()) {
-                return token;
+                return activity;
             }
         }
         return null;
     }
 
-    AppWindowToken getTopVisibleAppToken() {
+    ActivityRecord getTopVisibleActivity() {
         for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final AppWindowToken token = mChildren.get(i);
+            final ActivityRecord token = mChildren.get(i);
             // skip hidden (or about to hide) apps
             if (!token.mIsExiting && !token.isClientHidden() && !token.hiddenRequested) {
                 return token;
@@ -674,18 +677,18 @@
         return null;
     }
 
-    void positionChildAtTop(AppWindowToken aToken) {
-        positionChildAt(aToken, POSITION_TOP);
+    void positionChildAtTop(ActivityRecord child) {
+        positionChildAt(child, POSITION_TOP);
     }
 
-    void positionChildAt(AppWindowToken aToken, int position) {
-        if (aToken == null) {
+    void positionChildAt(ActivityRecord child, int position) {
+        if (child == null) {
             Slog.w(TAG_WM,
                     "Attempted to position of non-existing app");
             return;
         }
 
-        positionChildAt(position, aToken, false /* includeParents */);
+        positionChildAt(position, child, false /* includeParents */);
     }
 
     void forceWindowsScaleable(boolean force) {
@@ -783,8 +786,8 @@
         super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
         proto.write(ID, mTaskId);
         for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final AppWindowToken appWindowToken = mChildren.get(i);
-            appWindowToken.writeToProto(proto, APP_WINDOW_TOKENS, logLevel);
+            final ActivityRecord activity = mChildren.get(i);
+            activity.writeToProto(proto, APP_WINDOW_TOKENS, logLevel);
         }
         proto.write(FILLS_PARENT, matchParentBounds());
         getBounds().writeToProto(proto, BOUNDS);
@@ -810,9 +813,9 @@
         final String quadruplePrefix = triplePrefix + "  ";
 
         for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final AppWindowToken wtoken = mChildren.get(i);
-            pw.println(triplePrefix + "Activity #" + i + " " + wtoken);
-            wtoken.dump(pw, quadruplePrefix, dumpAll);
+            final ActivityRecord activity = mChildren.get(i);
+            pw.println(triplePrefix + "Activity #" + i + " " + activity);
+            activity.dump(pw, quadruplePrefix, dumpAll);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index 56b3bba..ed07f30 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -172,7 +172,7 @@
         // on top (eg. a dialog window).
         WindowState transferFocusFromWin = win;
         if (displayContent.mCurrentFocus != null && displayContent.mCurrentFocus != win
-                && displayContent.mCurrentFocus.mAppToken == win.mAppToken) {
+                && displayContent.mCurrentFocus.mActivityRecord == win.mActivityRecord) {
             transferFocusFromWin = displayContent.mCurrentFocus;
         }
         if (!mInputManager.transferTouchFocus(
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 75333c7..299b32c 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -48,7 +48,7 @@
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
 import static android.view.Display.DEFAULT_DISPLAY;
 
@@ -447,7 +447,7 @@
     }
 
     void cleanUpResourcesForDestroy() {
-        if (!mActivities.isEmpty()) {
+        if (hasChild()) {
             return;
         }
 
@@ -553,7 +553,7 @@
             // This method assumes that the task is already placed in the right stack.
             // we do not mess with that decision and we only do the resize!
 
-            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + mTaskId);
+            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizeTask_" + mTaskId);
 
             boolean updatedConfig = false;
             mTmpConfig.setTo(getResolvedOverrideConfiguration());
@@ -587,7 +587,7 @@
 
             saveLaunchingStateIfNeeded();
 
-            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
             return kept;
         } finally {
             mAtmService.continueWindowLayout();
@@ -1095,7 +1095,7 @@
             // There are no non-finishing activities in the task.
             return null;
         }
-        return mActivities.get(rootActivityIndex);
+        return getChildAt(rootActivityIndex);
     }
 
     ActivityRecord getTopActivity() {
@@ -1103,8 +1103,8 @@
     }
 
     ActivityRecord getTopActivity(boolean includeOverlays) {
-        for (int i = mActivities.size() - 1; i >= 0; --i) {
-            final ActivityRecord r = mActivities.get(i);
+        for (int i = getChildCount() - 1; i >= 0; --i) {
+            final ActivityRecord r = getChildAt(i);
             if (r.finishing || (!includeOverlays && r.mTaskOverlay)) {
                 continue;
             }
@@ -1115,8 +1115,8 @@
 
     ActivityRecord topRunningActivityLocked() {
         if (mStack != null) {
-            for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
-                ActivityRecord r = mActivities.get(activityNdx);
+            for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                ActivityRecord r = getChildAt(activityNdx);
                 if (!r.finishing && r.okToShowLocked()) {
                     return r;
                 }
@@ -1126,8 +1126,8 @@
     }
 
     boolean isVisible() {
-        for (int i = mActivities.size() - 1; i >= 0; --i) {
-            final ActivityRecord r = mActivities.get(i);
+        for (int i = getChildCount() - 1; i >= 0; --i) {
+            final ActivityRecord r = getChildAt(i);
             if (r.visible) {
                 return true;
             }
@@ -1139,8 +1139,8 @@
      * Return true if any activities in this task belongs to input uid.
      */
     boolean containsAppUid(int uid) {
-        for (int i = mActivities.size() - 1; i >= 0; --i) {
-            final ActivityRecord r = mActivities.get(i);
+        for (int i = getChildCount() - 1; i >= 0; --i) {
+            final ActivityRecord r = getChildAt(i);
             if (r.getUid() == uid) {
                 return true;
             }
@@ -1150,8 +1150,8 @@
 
     void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
         if (mStack != null) {
-            for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
-                ActivityRecord r = mActivities.get(activityNdx);
+            for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                ActivityRecord r = getChildAt(activityNdx);
                 if (!r.finishing && r.okToShowLocked() && r.visibleIgnoringKeyguard) {
                     outActivities.add(r);
                 }
@@ -1161,8 +1161,8 @@
 
     ActivityRecord topRunningActivityWithStartingWindowLocked() {
         if (mStack != null) {
-            for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
-                ActivityRecord r = mActivities.get(activityNdx);
+            for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+                ActivityRecord r = getChildAt(activityNdx);
                 if (r.mStartingWindowState != STARTING_WINDOW_SHOWN
                         || r.finishing || !r.okToShowLocked()) {
                     continue;
@@ -1179,8 +1179,8 @@
      */
     void getNumRunningActivities(TaskActivitiesReport reportOut) {
         reportOut.reset();
-        for (int i = mActivities.size() - 1; i >= 0; --i) {
-            final ActivityRecord r = mActivities.get(i);
+        for (int i = getChildCount() - 1; i >= 0; --i) {
+            final ActivityRecord r = getChildAt(i);
             if (r.finishing) {
                 continue;
             }
@@ -1227,17 +1227,17 @@
     }
 
     void addActivityToTop(ActivityRecord r) {
-        addActivityAtIndex(mActivities.size(), r);
+        addActivityAtIndex(getChildCount(), r);
     }
 
     @Override
     /*@WindowConfiguration.ActivityType*/
     public int getActivityType() {
         final int applicationType = super.getActivityType();
-        if (applicationType != ACTIVITY_TYPE_UNDEFINED || mActivities.isEmpty()) {
+        if (applicationType != ACTIVITY_TYPE_UNDEFINED || !hasChild()) {
             return applicationType;
         }
-        return mActivities.get(0).getActivityType();
+        return getChildAt(0).getActivityType();
     }
 
     /**
@@ -1259,7 +1259,7 @@
             numFullscreen++;
         }
         // Only set this based on the first activity
-        if (mActivities.isEmpty()) {
+        if (!hasChild()) {
             if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
                 // Normally non-standard activity type for the activity record will be set when the
                 // object is created, however we delay setting the standard application type until
@@ -1279,10 +1279,10 @@
             r.setActivityType(getActivityType());
         }
 
-        final int size = mActivities.size();
+        final int size = getChildCount();
 
         if (index == size && size > 0) {
-            final ActivityRecord top = mActivities.get(size - 1);
+            final ActivityRecord top = getChildAt(size - 1);
             if (top.mTaskOverlay) {
                 // Place below the task overlay activity since the overlay activity should always
                 // be on top.
@@ -1341,7 +1341,7 @@
             mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
         }
 
-        if (mActivities.isEmpty()) {
+        if (!hasChild()) {
             return !mReuseTask;
         }
         updateEffectiveIntent();
@@ -1355,8 +1355,8 @@
      */
     boolean onlyHasTaskOverlayActivities(boolean excludeFinishing) {
         int count = 0;
-        for (int i = mActivities.size() - 1; i >= 0; i--) {
-            final ActivityRecord r = mActivities.get(i);
+        for (int i = getChildCount() - 1; i >= 0; i--) {
+            final ActivityRecord r = getChildAt(i);
             if (excludeFinishing && r.finishing) {
                 continue;
             }
@@ -1372,7 +1372,7 @@
         // We will automatically remove the task either if it has explicitly asked for
         // this, or it is empty and has never contained an activity that got shown to
         // the user.
-        return autoRemoveRecents || (mActivities.isEmpty() && !hasBeenVisible);
+        return autoRemoveRecents || (!hasChild() && !hasBeenVisible);
     }
 
     /**
@@ -1380,9 +1380,9 @@
      * task starting at a specified index.
      */
     final void performClearTaskAtIndexLocked(int activityNdx, String reason) {
-        int numActivities = mActivities.size();
+        int numActivities = getChildCount();
         for ( ; activityNdx < numActivities; ++activityNdx) {
-            final ActivityRecord r = mActivities.get(activityNdx);
+            final ActivityRecord r = getChildAt(activityNdx);
             if (r.finishing) {
                 continue;
             }
@@ -1429,9 +1429,9 @@
      * or null if none was found.
      */
     final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
-        int numActivities = mActivities.size();
+        int numActivities = getChildCount();
         for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
-            ActivityRecord r = mActivities.get(activityNdx);
+            ActivityRecord r = getChildAt(activityNdx);
             if (r.finishing) {
                 continue;
             }
@@ -1440,7 +1440,7 @@
                 final ActivityRecord ret = r;
 
                 for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
-                    r = mActivities.get(activityNdx);
+                    r = getChildAt(activityNdx);
                     if (r.finishing) {
                         continue;
                     }
@@ -1591,8 +1591,8 @@
      */
     final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) {
         final ComponentName realActivity = r.mActivityComponent;
-        for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
-            ActivityRecord candidate = mActivities.get(activityNdx);
+        for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+            ActivityRecord candidate = getChildAt(activityNdx);
             if (candidate.finishing) {
                 continue;
             }
@@ -1609,12 +1609,12 @@
         // Traverse upwards looking for any break between main task activities and
         // utility activities.
         int activityNdx;
-        final int numActivities = mActivities.size();
+        final int numActivities = getChildCount();
         final boolean relinquish = numActivities != 0 &&
-                (mActivities.get(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
+                (getChildAt(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
         for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
                 ++activityNdx) {
-            final ActivityRecord r = mActivities.get(activityNdx);
+            final ActivityRecord r = getChildAt(activityNdx);
             if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
                 // This will be the top activity for determining taskDescription. Pre-inc to
                 // overcome initial decrement below.
@@ -1642,7 +1642,7 @@
             boolean navigationBarContrastWhenTransparent = false;
             boolean topActivity = true;
             for (--activityNdx; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = mActivities.get(activityNdx);
+                final ActivityRecord r = getChildAt(activityNdx);
                 if (r.mTaskOverlay) {
                     continue;
                 }
@@ -1697,9 +1697,9 @@
      */
     int findRootIndex(boolean effectiveRoot) {
         int effectiveNdx = -1;
-        final int topActivityNdx = mActivities.size() - 1;
+        final int topActivityNdx = getChildCount() - 1;
         for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
-            final ActivityRecord r = mActivities.get(activityNdx);
+            final ActivityRecord r = getChildAt(activityNdx);
             if (r.finishing) {
                 continue;
             }
@@ -1720,7 +1720,7 @@
             // But we still want to update the intent, so let's use the bottom activity.
             effectiveRootIndex = 0;
         }
-        final ActivityRecord r = mActivities.get(effectiveRootIndex);
+        final ActivityRecord r = getChildAt(effectiveRootIndex);
         setIntent(r);
 
         // Update the task description when the activities change
@@ -2289,8 +2289,8 @@
     }
 
     void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
-        for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
-            final ActivityRecord r = mActivities.get(activityNdx);
+        for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+            final ActivityRecord r = getChildAt(activityNdx);
             if (r.visible) {
                 r.showStartingWindow(null /* prev */, false /* newTask */, taskSwitch);
             }
@@ -2462,7 +2462,7 @@
             sb.append(" StackId=");
             sb.append(getStackId());
             sb.append(" sz=");
-            sb.append(mActivities.size());
+            sb.append(getChildCount());
             sb.append('}');
             return sb.toString();
         }
@@ -2495,8 +2495,8 @@
         final long token = proto.start(fieldId);
         super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
         proto.write(ID, mTaskId);
-        for (int i = mActivities.size() - 1; i >= 0; i--) {
-            ActivityRecord activity = mActivities.get(i);
+        for (int i = getChildCount() - 1; i >= 0; i--) {
+            ActivityRecord activity = getChildAt(i);
             activity.writeToProto(proto, ACTIVITIES);
         }
         proto.write(STACK_ID, mStack.mStackId);
@@ -2607,10 +2607,9 @@
             out.endTag(null, TAG_INTENT);
         }
 
-        final ArrayList<ActivityRecord> activities = mActivities;
-        final int numActivities = activities.size();
+        final int numActivities = getChildCount();
         for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
-            final ActivityRecord r = activities.get(activityNdx);
+            final ActivityRecord r = getChildAt(activityNdx);
             if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() ||
                     ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
                             | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) &&
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotCache.java b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
index 8175c4a..9e55113 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotCache.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
@@ -34,7 +34,7 @@
 
     private final WindowManagerService mService;
     private final TaskSnapshotLoader mLoader;
-    private final ArrayMap<AppWindowToken, Integer> mAppTaskMap = new ArrayMap<>();
+    private final ArrayMap<ActivityRecord, Integer> mAppTaskMap = new ArrayMap<>();
     private final ArrayMap<Integer, CacheEntry> mRunningCache = new ArrayMap<>();
 
     TaskSnapshotCache(WindowManagerService service, TaskSnapshotLoader loader) {
@@ -47,7 +47,7 @@
         if (entry != null) {
             mAppTaskMap.remove(entry.topApp);
         }
-        final AppWindowToken top = task.getTopChild();
+        final ActivityRecord top = task.getTopChild();
         mAppTaskMap.put(top, task.mTaskId);
         mRunningCache.put(task.mTaskId, new CacheEntry(snapshot, task.getTopChild()));
     }
@@ -87,8 +87,8 @@
     /**
      * Called when an app token has been removed
      */
-    void onAppRemoved(AppWindowToken wtoken) {
-        final Integer taskId = mAppTaskMap.get(wtoken);
+    void onAppRemoved(ActivityRecord activity) {
+        final Integer taskId = mAppTaskMap.get(activity);
         if (taskId != null) {
             removeRunningEntry(taskId);
         }
@@ -97,8 +97,8 @@
     /**
      * Callend when an app window token's process died.
      */
-    void onAppDied(AppWindowToken wtoken) {
-        final Integer taskId = mAppTaskMap.get(wtoken);
+    void onAppDied(ActivityRecord activity) {
+        final Integer taskId = mAppTaskMap.get(activity);
         if (taskId != null) {
             removeRunningEntry(taskId);
         }
@@ -134,9 +134,9 @@
         final TaskSnapshot snapshot;
 
         /** The app token that was on top of the task when the snapshot was taken */
-        final AppWindowToken topApp;
+        final ActivityRecord topApp;
 
-        CacheEntry(TaskSnapshot snapshot, AppWindowToken topApp) {
+        CacheEntry(TaskSnapshot snapshot, ActivityRecord topApp) {
             this.snapshot = snapshot;
             this.topApp = topApp;
         }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index f9a6fe7..0d4ec65 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -140,13 +140,13 @@
     /**
      * Called when the visibility of an app changes outside of the regular app transition flow.
      */
-    void notifyAppVisibilityChanged(AppWindowToken appWindowToken, boolean visible) {
+    void notifyAppVisibilityChanged(ActivityRecord appWindowToken, boolean visible) {
         if (!visible) {
             handleClosingApps(Sets.newArraySet(appWindowToken));
         }
     }
 
-    private void handleClosingApps(ArraySet<AppWindowToken> closingApps) {
+    private void handleClosingApps(ArraySet<ActivityRecord> closingApps) {
         if (shouldDisableSnapshots()) {
             return;
         }
@@ -215,9 +215,9 @@
      * Creates a starting surface for {@param token} with {@param snapshot}. DO NOT HOLD THE WINDOW
      * MANAGER LOCK WHEN CALLING THIS METHOD!
      */
-    StartingSurface createStartingSurface(AppWindowToken token,
+    StartingSurface createStartingSurface(ActivityRecord activity,
             TaskSnapshot snapshot) {
-        return TaskSnapshotSurface.create(mService, token, snapshot);
+        return TaskSnapshotSurface.create(mService, activity, snapshot);
     }
 
     /**
@@ -225,21 +225,21 @@
      * we're looking for, but during app transitions, trampoline activities can appear in the
      * children, which should be ignored.
      */
-    @Nullable private AppWindowToken findAppTokenForSnapshot(Task task) {
+    @Nullable private ActivityRecord findAppTokenForSnapshot(Task task) {
         for (int i = task.getChildCount() - 1; i >= 0; --i) {
-            final AppWindowToken appWindowToken = task.getChildAt(i);
-            if (appWindowToken == null || !appWindowToken.isSurfaceShowing()
-                    || appWindowToken.findMainWindow() == null) {
+            final ActivityRecord activity = task.getChildAt(i);
+            if (activity == null || !activity.isSurfaceShowing()
+                    || activity.findMainWindow() == null) {
                 continue;
             }
-            final boolean hasVisibleChild = appWindowToken.forAllWindows(
+            final boolean hasVisibleChild = activity.forAllWindows(
                     // Ensure at least one window for the top app is visible before attempting to
                     // take a screenshot. Visible here means that the WSA surface is shown and has
                     // an alpha greater than 0.
                     ws -> ws.mWinAnimator != null && ws.mWinAnimator.getShown()
                             && ws.mWinAnimator.mLastAlpha > 0f, true  /* traverseTopToBottom */);
             if (hasVisibleChild) {
-                return appWindowToken;
+                return activity;
             }
         }
         return null;
@@ -275,16 +275,16 @@
             return null;
         }
 
-        final AppWindowToken appWindowToken = findAppTokenForSnapshot(task);
-        if (appWindowToken == null) {
+        final ActivityRecord activity = findAppTokenForSnapshot(task);
+        if (activity == null) {
             if (DEBUG_SCREENSHOT) {
                 Slog.w(TAG_WM, "Failed to take screenshot. No visible windows for " + task);
             }
             return null;
         }
-        if (appWindowToken.hasCommittedReparentToAnimationLeash()) {
+        if (activity.hasCommittedReparentToAnimationLeash()) {
             if (DEBUG_SCREENSHOT) {
-                Slog.w(TAG_WM, "Failed to take screenshot. App is animating " + appWindowToken);
+                Slog.w(TAG_WM, "Failed to take screenshot. App is animating " + activity);
             }
             return null;
         }
@@ -294,7 +294,7 @@
                 ? mPersister.getReducedScale()
                 : mFullSnapshotScale;
 
-        final WindowState mainWindow = appWindowToken.findMainWindow();
+        final WindowState mainWindow = activity.findMainWindow();
         if (mainWindow == null) {
             Slog.w(TAG_WM, "Failed to take screenshot. No main window for " + task);
             return null;
@@ -311,12 +311,12 @@
         final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE;
         return new TaskSnapshot(
                 System.currentTimeMillis() /* id */,
-                appWindowToken.mActivityComponent, screenshotBuffer.getGraphicBuffer(),
+                activity.mActivityComponent, screenshotBuffer.getGraphicBuffer(),
                 screenshotBuffer.getColorSpace(),
-                appWindowToken.getTask().getConfiguration().orientation,
+                activity.getTask().getConfiguration().orientation,
                 getInsets(mainWindow), isLowRamDevice /* reduced */, scaleFraction /* scale */,
                 true /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
-                !appWindowToken.fillsParent() || isWindowTranslucent);
+                !activity.fillsParent() || isWindowTranslucent);
     }
 
     private boolean shouldDisableSnapshots() {
@@ -327,7 +327,7 @@
         // XXX(b/72757033): These are insets relative to the window frame, but we're really
         // interested in the insets relative to the task bounds.
         final Rect insets = minRect(state.getContentInsets(), state.getStableInsets());
-        InsetUtils.addInsets(insets, state.mAppToken.getLetterboxInsets());
+        InsetUtils.addInsets(insets, state.mActivityRecord.getLetterboxInsets());
         return insets;
     }
 
@@ -342,11 +342,11 @@
      * Retrieves all closing tasks based on the list of closing apps during an app transition.
      */
     @VisibleForTesting
-    void getClosingTasks(ArraySet<AppWindowToken> closingApps, ArraySet<Task> outClosingTasks) {
+    void getClosingTasks(ArraySet<ActivityRecord> closingApps, ArraySet<Task> outClosingTasks) {
         outClosingTasks.clear();
         for (int i = closingApps.size() - 1; i >= 0; i--) {
-            final AppWindowToken atoken = closingApps.valueAt(i);
-            final Task task = atoken.getTask();
+            final ActivityRecord activity = closingApps.valueAt(i);
+            final Task task = activity.getTask();
 
             // If the task of the app is not visible anymore, it means no other app in that task
             // is opening. Thus, the task is closing.
@@ -358,7 +358,7 @@
 
     @VisibleForTesting
     int getSnapshotMode(Task task) {
-        final AppWindowToken topChild = task.getTopChild();
+        final ActivityRecord topChild = task.getTopChild();
         if (!task.isActivityTypeStandardOrUndefined() && !task.isActivityTypeAssistant()) {
             return SNAPSHOT_MODE_NONE;
         } else if (topChild != null && topChild.shouldUseAppThemeSnapshot()) {
@@ -373,7 +373,7 @@
      * as possible by using the theme's window background.
      */
     private TaskSnapshot drawAppThemeSnapshot(Task task) {
-        final AppWindowToken topChild = task.getTopChild();
+        final ActivityRecord topChild = task.getTopChild();
         if (topChild == null) {
             return null;
         }
@@ -415,17 +415,17 @@
     }
 
     /**
-     * Called when an {@link AppWindowToken} has been removed.
+     * Called when an {@link ActivityRecord} has been removed.
      */
-    void onAppRemoved(AppWindowToken wtoken) {
-        mCache.onAppRemoved(wtoken);
+    void onAppRemoved(ActivityRecord activity) {
+        mCache.onAppRemoved(activity);
     }
 
     /**
-     * Called when the process of an {@link AppWindowToken} has died.
+     * Called when the process of an {@link ActivityRecord} has died.
      */
-    void onAppDied(AppWindowToken wtoken) {
-        mCache.onAppDied(wtoken);
+    void onAppDied(ActivityRecord activity) {
+        mCache.onAppDied(activity);
     }
 
     void notifyTaskRemovedFromRecents(int taskId, int userId) {
@@ -481,9 +481,9 @@
      *         {@param task}.
      */
     private int getSystemUiVisibility(Task task) {
-        final AppWindowToken topFullscreenToken = task.getTopFullscreenAppToken();
-        final WindowState topFullscreenWindow = topFullscreenToken != null
-                ? topFullscreenToken.getTopFullscreenWindow()
+        final ActivityRecord topFullscreenActivity = task.getTopFullscreenActivity();
+        final WindowState topFullscreenWindow = topFullscreenActivity != null
+                ? topFullscreenActivity.getTopFullscreenWindow()
                 : null;
         if (topFullscreenWindow != null) {
             return topFullscreenWindow.getSystemUiVisibility();
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 172ebce..b1e5c8f 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -136,7 +136,7 @@
     private final int mOrientationOnCreation;
     private final SurfaceControl.Transaction mTransaction;
 
-    static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token,
+    static TaskSnapshotSurface create(WindowManagerService service, ActivityRecord activity,
             TaskSnapshot snapshot) {
 
         final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
@@ -159,23 +159,24 @@
         final int windowPrivateFlags;
         final int currentOrientation;
         synchronized (service.mGlobalLock) {
-            final WindowState mainWindow = token.findMainWindow();
-            final Task task = token.getTask();
+            final WindowState mainWindow = activity.findMainWindow();
+            final Task task = activity.getTask();
             if (task == null) {
-                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for token="
-                        + token);
+                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for activity="
+                        + activity);
                 return null;
             }
-            final AppWindowToken topFullscreenToken = token.getTask().getTopFullscreenAppToken();
-            if (topFullscreenToken == null) {
+            final ActivityRecord topFullscreenActivity =
+                    activity.getTask().getTopFullscreenActivity();
+            if (topFullscreenActivity == null) {
                 Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find top fullscreen for task="
                         + task);
                 return null;
             }
-            final WindowState topFullscreenWindow = topFullscreenToken.getTopFullscreenWindow();
+            final WindowState topFullscreenWindow = topFullscreenActivity.getTopFullscreenWindow();
             if (mainWindow == null || topFullscreenWindow == null) {
-                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token="
-                        + token);
+                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for activity="
+                        + activity);
                 return null;
             }
             sysUiVis = topFullscreenWindow.getSystemUiVisibility();
@@ -191,7 +192,7 @@
                     | FLAG_NOT_FOCUSABLE
                     | FLAG_NOT_TOUCHABLE;
             layoutParams.privateFlags = windowPrivateFlags & PRIVATE_FLAG_INHERITS;
-            layoutParams.token = token.token;
+            layoutParams.token = activity.token;
             layoutParams.width = LayoutParams.MATCH_PARENT;
             layoutParams.height = LayoutParams.MATCH_PARENT;
             layoutParams.systemUiVisibility = sysUiVis;
@@ -207,7 +208,7 @@
         }
         try {
             final int res = session.addToDisplay(window, window.mSeq, layoutParams,
-                    View.GONE, token.getDisplayContent().getDisplayId(), tmpFrame, tmpRect, tmpRect,
+                    View.GONE, activity.getDisplayContent().getDisplayId(), tmpFrame, tmpRect, tmpRect,
                     tmpRect, tmpCutout, null, mTmpInsetsState);
             if (res < 0) {
                 Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 10d8328..fc9a110 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -78,6 +78,7 @@
 import com.android.server.EventLogTags;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.List;
 
 public class TaskStack extends WindowContainer<Task> implements
@@ -110,9 +111,9 @@
      */
     private final Rect mFullyAdjustedImeBounds = new Rect();
 
-    /** Application tokens that are exiting, but still on screen for animations. */
-    final AppTokenList mExitingAppTokens = new AppTokenList();
-    final AppTokenList mTmpAppTokens = new AppTokenList();
+    /** ActivityRecords that are exiting, but still on screen for animations. */
+    final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
+    final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>();
 
     /** Detach this stack from its display when animation completes. */
     // TODO: maybe tie this to WindowContainer#removeChild some how...
@@ -153,8 +154,8 @@
     final Rect mTmpDimBoundsRect = new Rect();
     private final Point mLastSurfaceSize = new Point();
 
-    private final AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry =
-            new AnimatingAppWindowTokenRegistry();
+    private final AnimatingActivityRegistry mAnimatingActivityRegistry =
+            new AnimatingActivityRegistry();
 
     TaskStack(WindowManagerService service, int stackId, ActivityStack activityStack) {
         super(service);
@@ -676,11 +677,11 @@
             }
             mDisplayContent.setLayoutNeeded();
         }
-        for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) {
-            final AppWindowToken wtoken = mExitingAppTokens.get(appNdx);
-            if (wtoken.getTask() == task) {
-                wtoken.mIsExiting = false;
-                mExitingAppTokens.remove(appNdx);
+        for (int appNdx = mExitingActivities.size() - 1; appNdx >= 0; --appNdx) {
+            final ActivityRecord activity = mExitingActivities.get(appNdx);
+            if (activity.getTask() == task) {
+                activity.mIsExiting = false;
+                mExitingActivities.remove(appNdx);
             }
         }
     }
@@ -1327,18 +1328,18 @@
         for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
             mChildren.get(taskNdx).dump(pw, prefix + "  ", dumpAll);
         }
-        if (!mExitingAppTokens.isEmpty()) {
+        if (!mExitingActivities.isEmpty()) {
             pw.println();
             pw.println("  Exiting application tokens:");
-            for (int i = mExitingAppTokens.size() - 1; i >= 0; i--) {
-                WindowToken token = mExitingAppTokens.get(i);
+            for (int i = mExitingActivities.size() - 1; i >= 0; i--) {
+                WindowToken token = mExitingActivities.get(i);
                 pw.print("  Exiting App #"); pw.print(i);
                 pw.print(' '); pw.print(token);
                 pw.println(':');
                 token.dump(pw, "    ", dumpAll);
             }
         }
-        mAnimatingAppWindowTokenRegistry.dump(pw, "AnimatingApps:", prefix);
+        mAnimatingActivityRegistry.dump(pw, "AnimatingApps:", prefix);
     }
 
     @Override
@@ -1435,8 +1436,8 @@
             Rect contentRect, Rect postExclude) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final Task task = mChildren.get(i);
-            AppWindowToken token = task.getTopVisibleAppToken();
-            if (token == null || !token.hasContentToDisplay()) {
+            ActivityRecord topVisibleActivity = task.getTopVisibleActivity();
+            if (topVisibleActivity == null || !topVisibleActivity.hasContentToDisplay()) {
                 continue;
             }
 
@@ -1747,7 +1748,7 @@
             if (homeTask == null) {
                 return true;
             }
-            final AppWindowToken homeApp = homeTask.getTopVisibleAppToken();
+            final ActivityRecord homeApp = homeTask.getTopVisibleActivity();
             if (!homeTask.isVisible() || homeApp == null) {
                 return true;
             }
@@ -1862,7 +1863,7 @@
         scheduleAnimation();
     }
 
-    AnimatingAppWindowTokenRegistry getAnimatingAppWindowTokenRegistry() {
-        return mAnimatingAppWindowTokenRegistry;
+    AnimatingActivityRegistry getAnimatingActivityRegistry() {
+        return mAnimatingActivityRegistry;
     }
 }
diff --git a/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
index 01abcab..61e9e50 100644
--- a/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
+++ b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
@@ -29,7 +29,7 @@
 import java.io.PrintWriter;
 
 /**
- * Manages the set of {@link AppWindowToken}s for which we don't know yet whether it's visible or
+ * Manages the set of {@link ActivityRecord}s for which we don't know yet whether it's visible or
  * not. This happens when starting an activity while the lockscreen is showing. In that case, the
  * keyguard flags an app might set influence it's visibility, so we wait until this is resolved to
  * start the transition to avoid flickers.
@@ -56,7 +56,7 @@
 
     // Set of apps for which we don't know yet whether it's visible or not, depending on what kind
     // of lockscreen flags the app might set during its first relayout.
-    private final ArrayMap<AppWindowToken, Integer> mUnknownApps = new ArrayMap<>();
+    private final ArrayMap<ActivityRecord, Integer> mUnknownApps = new ArrayMap<>();
 
     private final WindowManagerService mService;
 
@@ -87,52 +87,52 @@
         return builder.toString();
     }
 
-    void appRemovedOrHidden(@NonNull AppWindowToken appWindow) {
+    void appRemovedOrHidden(@NonNull ActivityRecord activity) {
         if (DEBUG_UNKNOWN_APP_VISIBILITY) {
-            Slog.d(TAG, "App removed or hidden appWindow=" + appWindow);
+            Slog.d(TAG, "App removed or hidden activity=" + activity);
         }
-        mUnknownApps.remove(appWindow);
+        mUnknownApps.remove(activity);
     }
 
     /**
-     * Notifies that {@param appWindow} has been launched behind Keyguard, and we need to wait until
+     * Notifies that {@param activity} has been launched behind Keyguard, and we need to wait until
      * it is resumed and relaid out to resolve the visibility.
      */
-    void notifyLaunched(@NonNull AppWindowToken appWindow) {
+    void notifyLaunched(@NonNull ActivityRecord activity) {
         if (DEBUG_UNKNOWN_APP_VISIBILITY) {
-            Slog.d(TAG, "App launched appWindow=" + appWindow);
+            Slog.d(TAG, "App launched activity=" + activity);
         }
-        mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_RESUME);
+        mUnknownApps.put(activity, UNKNOWN_STATE_WAITING_RESUME);
     }
 
     /**
-     * Notifies that {@param appWindow} has finished resuming.
+     * Notifies that {@param activity} has finished resuming.
      */
-    void notifyAppResumedFinished(@NonNull AppWindowToken appWindow) {
-        if (mUnknownApps.containsKey(appWindow)
-                && mUnknownApps.get(appWindow) == UNKNOWN_STATE_WAITING_RESUME) {
+    void notifyAppResumedFinished(@NonNull ActivityRecord activity) {
+        if (mUnknownApps.containsKey(activity)
+                && mUnknownApps.get(activity) == UNKNOWN_STATE_WAITING_RESUME) {
             if (DEBUG_UNKNOWN_APP_VISIBILITY) {
-                Slog.d(TAG, "App resume finished appWindow=" + appWindow);
+                Slog.d(TAG, "App resume finished activity=" + activity);
             }
-            mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_RELAYOUT);
+            mUnknownApps.put(activity, UNKNOWN_STATE_WAITING_RELAYOUT);
         }
     }
 
     /**
-     * Notifies that {@param appWindow} has relaid out.
+     * Notifies that {@param activity} has relaid out.
      */
-    void notifyRelayouted(@NonNull AppWindowToken appWindow) {
-        if (!mUnknownApps.containsKey(appWindow)) {
+    void notifyRelayouted(@NonNull ActivityRecord activity) {
+        if (!mUnknownApps.containsKey(activity)) {
             return;
         }
         if (DEBUG_UNKNOWN_APP_VISIBILITY) {
-            Slog.d(TAG, "App relayouted appWindow=" + appWindow);
+            Slog.d(TAG, "App relayouted appWindow=" + activity);
         }
-        int state = mUnknownApps.get(appWindow);
+        int state = mUnknownApps.get(activity);
         if (state == UNKNOWN_STATE_WAITING_RELAYOUT) {
-            mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE);
+            mUnknownApps.put(activity, UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE);
             mService.notifyKeyguardFlagsChanged(this::notifyVisibilitiesUpdated,
-                    appWindow.getDisplayContent().getDisplayId());
+                    activity.getDisplayContent().getDisplayId());
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index e7b09db..1e13aef 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -118,7 +118,7 @@
         }
 
         mFindResults.resetTopWallpaper = true;
-        if (w.mAppToken != null && w.mAppToken.isHidden() && !w.mAppToken.isSelfAnimating()) {
+        if (w.mActivityRecord != null && w.mActivityRecord.isHidden() && !w.mActivityRecord.isSelfAnimating()) {
 
             // If this window's app token is hidden and not animating, it is of no interest to us.
             if (DEBUG_WALLPAPER) Slog.v(TAG, "Skipping hidden and not animating token: " + w);
@@ -135,10 +135,10 @@
             mFindResults.setUseTopWallpaperAsTarget(true);
         }
 
-        final boolean keyguardGoingAwayWithWallpaper = (w.mAppToken != null
-                && w.mAppToken.isSelfAnimating()
-                && AppTransition.isKeyguardGoingAwayTransit(w.mAppToken.getTransit())
-                && (w.mAppToken.getTransitFlags()
+        final boolean keyguardGoingAwayWithWallpaper = (w.mActivityRecord != null
+                && w.mActivityRecord.isSelfAnimating()
+                && AppTransition.isKeyguardGoingAwayTransit(w.mActivityRecord.getTransit())
+                && (w.mActivityRecord.getTransitFlags()
                         & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
 
         boolean needsShowWhenLockedWallpaper = false;
@@ -148,7 +148,7 @@
             // The lowest show when locked window decides whether we need to put the wallpaper
             // behind.
             needsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
-                    || (w.mAppToken != null && !w.mAppToken.fillsParent());
+                    || (w.mActivityRecord != null && !w.mActivityRecord.fillsParent());
         }
 
         if (keyguardGoingAwayWithWallpaper || needsShowWhenLockedWallpaper) {
@@ -159,8 +159,8 @@
 
         final RecentsAnimationController recentsAnimationController =
                 mService.getRecentsAnimationController();
-        final boolean animationWallpaper = w.mAppToken != null && w.mAppToken.getAnimation() != null
-                && w.mAppToken.getAnimation().getShowWallpaper();
+        final boolean animationWallpaper = w.mActivityRecord != null && w.mActivityRecord.getAnimation() != null
+                && w.mActivityRecord.getAnimation().getShowWallpaper();
         final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0
                 || animationWallpaper;
         final boolean isRecentsTransitionTarget = (recentsAnimationController != null
@@ -223,22 +223,22 @@
                 && recentsAnimationController.isWallpaperVisible(wallpaperTarget);
         if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
                 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
-                + " animating=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
-                ? wallpaperTarget.mAppToken.isSelfAnimating() : null)
+                + " animating=" + ((wallpaperTarget != null && wallpaperTarget.mActivityRecord != null)
+                ? wallpaperTarget.mActivityRecord.isSelfAnimating() : null)
                 + " prev=" + mPrevWallpaperTarget
                 + " recentsAnimationWallpaperVisible=" + isAnimatingWithRecentsComponent);
         return (wallpaperTarget != null
                 && (!wallpaperTarget.mObscured
                         || isAnimatingWithRecentsComponent
-                        || (wallpaperTarget.mAppToken != null
-                                && wallpaperTarget.mAppToken.isSelfAnimating())))
+                        || (wallpaperTarget.mActivityRecord != null
+                                && wallpaperTarget.mActivityRecord.isSelfAnimating())))
                 || mPrevWallpaperTarget != null;
     }
 
     boolean isWallpaperTargetAnimating() {
         return mWallpaperTarget != null && mWallpaperTarget.isAnimating()
-                && (mWallpaperTarget.mAppToken == null
-                        || !mWallpaperTarget.mAppToken.isWaitingForTransitionStart());
+                && (mWallpaperTarget.mActivityRecord == null
+                        || !mWallpaperTarget.mActivityRecord.isWaitingForTransitionStart());
     }
 
     void updateWallpaperVisibility() {
@@ -527,10 +527,10 @@
             return;
         }
 
-        final boolean newTargetHidden = wallpaperTarget.mAppToken != null
-                && wallpaperTarget.mAppToken.hiddenRequested;
-        final boolean oldTargetHidden = prevWallpaperTarget.mAppToken != null
-                && prevWallpaperTarget.mAppToken.hiddenRequested;
+        final boolean newTargetHidden = wallpaperTarget.mActivityRecord != null
+                && wallpaperTarget.mActivityRecord.hiddenRequested;
+        final boolean oldTargetHidden = prevWallpaperTarget.mActivityRecord != null
+                && prevWallpaperTarget.mActivityRecord.hiddenRequested;
 
         if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Animating wallpapers:" + " old: "
                 + prevWallpaperTarget + " hidden=" + oldTargetHidden + " new: " + wallpaperTarget
@@ -544,9 +544,9 @@
             // is not. If they're both hidden, still use the new target.
             mWallpaperTarget = prevWallpaperTarget;
         } else if (newTargetHidden == oldTargetHidden
-                && !mDisplayContent.mOpeningApps.contains(wallpaperTarget.mAppToken)
-                && (mDisplayContent.mOpeningApps.contains(prevWallpaperTarget.mAppToken)
-                || mDisplayContent.mClosingApps.contains(prevWallpaperTarget.mAppToken))) {
+                && !mDisplayContent.mOpeningApps.contains(wallpaperTarget.mActivityRecord)
+                && (mDisplayContent.mOpeningApps.contains(prevWallpaperTarget.mActivityRecord)
+                || mDisplayContent.mClosingApps.contains(prevWallpaperTarget.mActivityRecord))) {
             // If they're both hidden (or both not hidden), prefer the one that's currently in
             // opening or closing app list, this allows transition selection logic to better
             // determine the wallpaper status of opening/closing apps.
@@ -661,23 +661,23 @@
      * Adjusts the wallpaper windows if the input display has a pending wallpaper layout or one of
      * the opening apps should be a wallpaper target.
      */
-    void adjustWallpaperWindowsForAppTransitionIfNeeded(ArraySet<AppWindowToken> openingApps,
-            ArraySet<AppWindowToken> changingApps) {
+    void adjustWallpaperWindowsForAppTransitionIfNeeded(ArraySet<ActivityRecord> openingApps,
+            ArraySet<ActivityRecord> changingApps) {
         boolean adjust = false;
         if ((mDisplayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
             adjust = true;
         } else {
             for (int i = openingApps.size() - 1; i >= 0; --i) {
-                final AppWindowToken token = openingApps.valueAt(i);
-                if (token.windowsCanBeWallpaperTarget()) {
+                final ActivityRecord activity = openingApps.valueAt(i);
+                if (activity.windowsCanBeWallpaperTarget()) {
                     adjust = true;
                     break;
                 }
             }
             if (!adjust) {
                 for (int i = changingApps.size() - 1; i >= 0; --i) {
-                    final AppWindowToken token = changingApps.valueAt(i);
-                    if (token.windowsCanBeWallpaperTarget()) {
+                    final ActivityRecord activity = changingApps.valueAt(i);
+                    if (activity.windowsCanBeWallpaperTarget()) {
                         adjust = true;
                         break;
                     }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index a4ab66a..037edf1 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -947,9 +947,9 @@
         wrapper.release();
     }
 
-    void forAllAppWindows(Consumer<AppWindowToken> callback) {
+    void forAllActivities(Consumer<ActivityRecord> callback) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
-            mChildren.get(i).forAllAppWindows(callback);
+            mChildren.get(i).forAllActivities(callback);
         }
     }
 
@@ -1446,7 +1446,7 @@
         final WindowManagerPolicy policy = mWmService.mPolicy;
         forAllWindows(w -> {
             final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
-            if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
+            if (w.isVisibleLw() && (w.mActivityRecord != null || keyguard)) {
                 w.mWinAnimator.mDrawState = DRAW_PENDING;
                 // Force add to mResizingWindows.
                 w.resetLastContentInsets();
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index f4b7672..0cb4826 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -514,6 +514,13 @@
     public abstract void showImePostLayout(IBinder imeTargetWindowToken);
 
     /**
+     * Hide IME using imeTargetWindow when requested.
+     *
+     * @param displayId on which IME is shown
+     */
+    public abstract void hideIme(int displayId);
+
+    /**
      * Tell window manager about a package that should not be running with high refresh rate
      * setting until removeNonHighRefreshRatePackage is called for the same package.
      *
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0287270..2dd6d0a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -236,6 +236,7 @@
 import android.view.SurfaceSession;
 import android.view.View;
 import android.view.WindowContentFrameStats;
+import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManager.RemoveContentMode;
@@ -530,7 +531,7 @@
      * List of app window tokens that are waiting for replacing windows. If the
      * replacement doesn't come in time the stale windows needs to be disposed of.
      */
-    final ArrayList<AppWindowToken> mWindowReplacementTimeouts = new ArrayList<>();
+    final ArrayList<ActivityRecord> mWindowReplacementTimeouts = new ArrayList<>();
 
     /**
      * Windows that are being resized.  Used so we can tell the client about
@@ -879,7 +880,7 @@
     /** The display that the rotation animation is applying to. */
     private int mFrozenDisplayId;
 
-    /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
+    /** Skip repeated ActivityRecords initialization. Note that AppWindowsToken's version of this
      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
     int mTransactionSequence;
 
@@ -989,7 +990,7 @@
         @Override
         public void onAppTransitionFinishedLocked(IBinder token) {
             mAtmInternal.notifyAppTransitionFinished();
-            final AppWindowToken atoken = mRoot.getAppWindowToken(token);
+            final ActivityRecord atoken = mRoot.getActivityRecord(token);
             if (atoken == null) {
                 return;
             }
@@ -1367,7 +1368,7 @@
                 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
             }
 
-            AppWindowToken atoken = null;
+            ActivityRecord activity = null;
             final boolean hasParent = parentWindow != null;
             // Use existing parent window token for child windows since they go in the same token
             // as there parent window so we can apply the same policy on them.
@@ -1433,16 +1434,16 @@
                         session.mCanAddInternalSystemWindow, isRoundedCornerOverlay);
             } else if (rootType >= FIRST_APPLICATION_WINDOW
                     && rootType <= LAST_APPLICATION_WINDOW) {
-                atoken = token.asAppWindowToken();
-                if (atoken == null) {
+                activity = token.asActivityRecord();
+                if (activity == null) {
                     ProtoLog.w(WM_ERROR, "Attempted to add window with non-application token "
                             + ".%s Aborting.", token);
                     return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
-                } else if (atoken.removed) {
+                } else if (activity.removed) {
                     ProtoLog.w(WM_ERROR, "Attempted to add window with exiting application token "
                             + ".%s Aborting.", token);
                     return WindowManagerGlobal.ADD_APP_EXITING;
-                } else if (type == TYPE_APPLICATION_STARTING && atoken.startingWindow != null) {
+                } else if (type == TYPE_APPLICATION_STARTING && activity.startingWindow != null) {
                     ProtoLog.w(WM_ERROR,
                             "Attempted to add starting window to token with already existing"
                                     + " starting window");
@@ -1494,8 +1495,8 @@
                             + "%s.  Aborting.", attrs.token);
                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-            } else if (token.asAppWindowToken() != null) {
-                ProtoLog.w(WM_ERROR, "Non-null appWindowToken for system window of rootType=%d",
+            } else if (token.asActivityRecord() != null) {
+                ProtoLog.w(WM_ERROR, "Non-null activity for system window of rootType=%d",
                         rootType);
                 // It is not valid to use an app token with other system types; we will
                 // instead make a new token for it (as if null had been passed in for the token).
@@ -1590,11 +1591,11 @@
             final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
             win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
 
-            final AppWindowToken aToken = token.asAppWindowToken();
-            if (type == TYPE_APPLICATION_STARTING && aToken != null) {
-                aToken.startingWindow = win;
+            final ActivityRecord tokenActivity = token.asActivityRecord();
+            if (type == TYPE_APPLICATION_STARTING && tokenActivity != null) {
+                tokenActivity.startingWindow = win;
                 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "addWindow: %s startingWindow=%s",
-                        aToken, win);
+                        activity, win);
             }
 
             boolean imMayMove = true;
@@ -1635,12 +1636,12 @@
             winAnimator.mEnterAnimationPending = true;
             winAnimator.mEnteringAnimation = true;
             // Check if we need to prepare a transition for replacing window first.
-            if (atoken != null && atoken.isVisible()
-                    && !prepareWindowReplacementTransition(atoken)) {
+            if (activity != null && activity.isVisible()
+                    && !prepareWindowReplacementTransition(activity)) {
                 // If not, check if need to set up a dummy transition during display freeze
                 // so that the unfreeze wait for the apps to draw. This might be needed if
                 // the app is relaunching.
-                prepareNoneTransitionForRelaunching(atoken);
+                prepareNoneTransitionForRelaunching(activity);
             }
 
             final DisplayFrames displayFrames = displayContent.mDisplayFrames;
@@ -1650,10 +1651,10 @@
                     displayContent.calculateDisplayCutoutForRotation(displayInfo.rotation));
             final Rect taskBounds;
             final boolean floatingStack;
-            if (atoken != null && atoken.getTask() != null) {
+            if (activity != null && activity.getTask() != null) {
                 taskBounds = mTmpRect;
-                atoken.getTask().getBounds(mTmpRect);
-                floatingStack = atoken.getTask().isFloating();
+                tokenActivity.getTask().getBounds(mTmpRect);
+                floatingStack = activity.getTask().isFloating();
             } else {
                 taskBounds = null;
                 floatingStack = false;
@@ -1667,7 +1668,7 @@
             if (mInTouchMode) {
                 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
             }
-            if (win.mAppToken == null || !win.mAppToken.isClientHidden()) {
+            if (win.mActivityRecord == null || !win.mActivityRecord.isClientHidden()) {
                 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
             }
 
@@ -1752,8 +1753,8 @@
             WindowState attachedWindow) {
         // Try using the target SDK of the root window
         if (attachedWindow != null) {
-            return attachedWindow.mAppToken != null
-                    && attachedWindow.mAppToken.mTargetSdk >= Build.VERSION_CODES.O;
+            return attachedWindow.mActivityRecord != null
+                    && attachedWindow.mActivityRecord.mTargetSdk >= Build.VERSION_CODES.O;
         } else {
             // Otherwise, look at the package
             try {
@@ -1777,9 +1778,9 @@
     /**
      * Returns true if we're done setting up any transitions.
      */
-    private boolean prepareWindowReplacementTransition(AppWindowToken atoken) {
-        atoken.clearAllDrawn();
-        final WindowState replacedWindow = atoken.getReplacingWindow();
+    private boolean prepareWindowReplacementTransition(ActivityRecord activity) {
+        activity.clearAllDrawn();
+        final WindowState replacedWindow = activity.getReplacingWindow();
         if (replacedWindow == null) {
             // We expect to already receive a request to remove the old window. If it did not
             // happen, let's just simply add a window.
@@ -1790,8 +1791,8 @@
         Rect frame = replacedWindow.getVisibleFrameLw();
         // We treat this as if this activity was opening, so we can trigger the app transition
         // animation and piggy-back on existing transition animation infrastructure.
-        final DisplayContent dc = atoken.getDisplayContent();
-        dc.mOpeningApps.add(atoken);
+        final DisplayContent dc = activity.getDisplayContent();
+        dc.mOpeningApps.add(activity);
         dc.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT,
                 0 /* flags */, false /* forceOverride */);
         dc.mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top,
@@ -1800,14 +1801,14 @@
         return true;
     }
 
-    private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) {
+    private void prepareNoneTransitionForRelaunching(ActivityRecord activity) {
         // Set up a none-transition and add the app to opening apps, so that the display
         // unfreeze wait for the apps to be drawn.
         // Note that if the display unfroze already because app unfreeze timed out,
         // we don't set up the transition anymore and just let it go.
-        final DisplayContent dc = atoken.getDisplayContent();
-        if (mDisplayFrozen && !dc.mOpeningApps.contains(atoken) && atoken.isRelaunching()) {
-            dc.mOpeningApps.add(atoken);
+        final DisplayContent dc = activity.getDisplayContent();
+        if (mDisplayFrozen && !dc.mOpeningApps.contains(activity) && activity.isRelaunching()) {
+            dc.mOpeningApps.add(activity);
             dc.prepareAppTransition(WindowManager.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT, 0 /* flags */,
                     false /* forceOverride */);
             dc.executeAppTransition();
@@ -1884,26 +1885,26 @@
         }
 
         final WindowToken token = win.mToken;
-        final AppWindowToken atoken = win.mAppToken;
+        final ActivityRecord activity = win.mActivityRecord;
         ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Removing %s from %s", win, token);
         // Window will already be removed from token before this post clean-up method is called.
         if (token.isEmpty()) {
             if (!token.mPersistOnEmpty) {
                 token.removeImmediately();
-            } else if (atoken != null) {
-                // TODO: Should this be moved into AppWindowToken.removeWindow? Might go away after
+            } else if (activity != null) {
+                // TODO: Should this be moved into ActivityRecord.removeWindow? Might go away after
                 // re-factor.
-                atoken.firstWindowDrawn = false;
-                atoken.clearAllDrawn();
-                final TaskStack stack = atoken.getStack();
+                activity.firstWindowDrawn = false;
+                activity.clearAllDrawn();
+                final TaskStack stack = activity.getStack();
                 if (stack != null) {
-                    stack.mExitingAppTokens.remove(atoken);
+                    stack.mExitingActivities.remove(activity);
                 }
             }
         }
 
-        if (atoken != null) {
-            atoken.postWindowRemoveStartingWindowCleanup(win);
+        if (activity != null) {
+            activity.postWindowRemoveStartingWindowCleanup(win);
         }
 
         if (win.mAttrs.type == TYPE_WALLPAPER) {
@@ -1916,8 +1917,8 @@
         if (dc != null && !mWindowPlacerLocked.isInLayout()) {
             dc.assignWindowLayers(true /* setLayoutNeeded */);
             mWindowPlacerLocked.performSurfacePlacement();
-            if (win.mAppToken != null) {
-                win.mAppToken.updateReportedVisibilityLocked();
+            if (win.mActivityRecord != null) {
+                win.mActivityRecord.updateReportedVisibilityLocked();
             }
         }
 
@@ -2124,9 +2125,9 @@
                         | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
                     win.mLayoutNeeded = true;
                 }
-                if (win.mAppToken != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
+                if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
                         || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {
-                    win.mAppToken.checkKeyguardFlagsChanged();
+                    win.mActivityRecord.checkKeyguardFlagsChanged();
                 }
                 if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0)
                         && (mAccessibilityController != null)) {
@@ -2195,8 +2196,8 @@
             // We should only relayout if the view is visible, it is a starting window, or the
             // associated appToken is not hidden.
             final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
-                    (win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
-                            || !win.mAppToken.isClientHidden());
+                    (win.mActivityRecord == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
+                            || !win.mActivityRecord.isClientHidden());
 
             // If we are not currently running the exit animation, we need to see about starting
             // one.
@@ -2301,8 +2302,8 @@
                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
             }
 
-            if (win.mAppToken != null) {
-                displayContent.mUnknownAppVisibilityController.notifyRelayouted(win.mAppToken);
+            if (win.mActivityRecord != null) {
+                displayContent.mUnknownAppVisibilityController.notifyRelayouted(win.mActivityRecord);
             }
 
             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: updateOrientation");
@@ -2314,8 +2315,8 @@
                 displayContent.mWallpaperController.updateWallpaperOffset(
                         win, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
             }
-            if (win.mAppToken != null) {
-                win.mAppToken.updateReportedVisibilityLocked();
+            if (win.mActivityRecord != null) {
+                win.mActivityRecord.updateReportedVisibilityLocked();
             }
             if (winAnimator.mReportSurfaceResized) {
                 winAnimator.mReportSurfaceResized = false;
@@ -2413,8 +2414,8 @@
             if (displayContent.mInputMethodWindow == win) {
                 displayContent.setInputMethodWindowLocked(null);
             }
-            boolean stopped = win.mAppToken != null ? win.mAppToken.mAppStopped : true;
-            // We set mDestroying=true so AppWindowToken#notifyAppStopped in-to destroy surfaces
+            boolean stopped = win.mActivityRecord != null ? win.mActivityRecord.mAppStopped : true;
+            // We set mDestroying=true so ActivityRecord#notifyAppStopped in-to destroy surfaces
             // will later actually destroy the surface if we do not do so here. Normally we leave
             // this to the exit animation.
             win.mDestroying = true;
@@ -2699,7 +2700,7 @@
     }
 
     void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
-        final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
+        final ActivityRecord wtoken = mRoot.getActivityRecord(token);
         if (wtoken != null) {
             wtoken.setMainWindowOpaque(isOpaque);
         }
@@ -4337,7 +4338,7 @@
         // to make room for IME, but the window is not the focused window that's taking input.
         // TODO (b/111080190): Consider the case of multiple IMEs on multi-display.
         final DisplayContent topFocusedDisplay = mRoot.getTopFocusedDisplayContent();
-        final AppWindowToken focusedApp = topFocusedDisplay.mFocusedApp;
+        final ActivityRecord focusedApp = topFocusedDisplay.mFocusedApp;
         return (focusedApp != null && focusedApp.getTask() != null)
                 ? focusedApp.getTask().mStack : null;
     }
@@ -4822,8 +4823,8 @@
                 case WINDOW_REPLACEMENT_TIMEOUT: {
                     synchronized (mGlobalLock) {
                         for (int i = mWindowReplacementTimeouts.size() - 1; i >= 0; i--) {
-                            final AppWindowToken token = mWindowReplacementTimeouts.get(i);
-                            token.onWindowReplacementTimeout();
+                            final ActivityRecord activity = mWindowReplacementTimeouts.get(i);
+                            activity.onWindowReplacementTimeout();
                         }
                         mWindowReplacementTimeouts.clear();
                     }
@@ -5996,7 +5997,7 @@
 
                 mRoot.forAllWindows((w) -> {
                     if ((!visibleOnly || w.mWinAnimator.getShown())
-                            && (!appsOnly || w.mAppToken != null)) {
+                            && (!appsOnly || w.mActivityRecord != null)) {
                         windows.add(w);
                     }
                 }, true /* traverseTopToBottom */);
@@ -6031,16 +6032,16 @@
      * the time an ANR occurred before anything else in the system changes
      * in response.
      *
-     * @param appWindowToken The application that ANR'd, may be null.
+     * @param activity The application that ANR'd, may be null.
      * @param windowState The window that ANR'd, may be null.
      * @param reason The reason for the ANR, may be null.
      */
-    void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, String reason) {
+    void saveANRStateLocked(ActivityRecord activity, WindowState windowState, String reason) {
         StringWriter sw = new StringWriter();
         PrintWriter pw = new FastPrintWriter(sw, false, 1024);
         pw.println("  ANR time: " + DateFormat.getDateTimeInstance().format(new Date()));
-        if (appWindowToken != null) {
-            pw.println("  Application at fault: " + appWindowToken.stringName);
+        if (activity != null) {
+            pw.println("  Application at fault: " + activity.stringName);
         }
         if (windowState != null) {
             pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
@@ -6286,19 +6287,19 @@
      * @param token Application token for which the activity will be relaunched.
      */
     void setWillReplaceWindow(IBinder token, boolean animate) {
-        final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
-        if (appWindowToken == null) {
+        final ActivityRecord activity = mRoot.getActivityRecord(token);
+        if (activity == null) {
             ProtoLog.w(WM_ERROR, "Attempted to set replacing window on non-existing app token %s",
                     token);
             return;
         }
-        if (!appWindowToken.hasContentToDisplay()) {
+        if (!activity.hasContentToDisplay()) {
             ProtoLog.w(WM_ERROR,
                     "Attempted to set replacing window on app token with no content %s",
                     token);
             return;
         }
-        appWindowToken.setWillReplaceWindows(animate);
+        activity.setWillReplaceWindows(animate);
     }
 
     /**
@@ -6315,14 +6316,14 @@
     // above. We should combine them or find better names.
     void setWillReplaceWindows(IBinder token, boolean childrenOnly) {
         synchronized (mGlobalLock) {
-            final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
-            if (appWindowToken == null) {
+            final ActivityRecord activity = mRoot.getActivityRecord(token);
+            if (activity == null) {
                 ProtoLog.w(WM_ERROR,
                         "Attempted to set replacing window on non-existing app token %s",
                         token);
                 return;
             }
-            if (!appWindowToken.hasContentToDisplay()) {
+            if (!activity.hasContentToDisplay()) {
                 ProtoLog.w(WM_ERROR,
                         "Attempted to set replacing window on app token with no content %s",
                         token);
@@ -6330,9 +6331,9 @@
             }
 
             if (childrenOnly) {
-                appWindowToken.setWillReplaceChildWindows();
+                activity.setWillReplaceChildWindows();
             } else {
-                appWindowToken.setWillReplaceWindows(false /* animate */);
+                activity.setWillReplaceWindows(false /* animate */);
             }
 
             scheduleClearWillReplaceWindows(token, true /* replacing */);
@@ -6349,22 +6350,22 @@
      * @param replacing Whether the window is being replaced or not.
      */
     void scheduleClearWillReplaceWindows(IBinder token, boolean replacing) {
-        final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
-        if (appWindowToken == null) {
+        final ActivityRecord activity = mRoot.getActivityRecord(token);
+        if (activity == null) {
             ProtoLog.w(WM_ERROR, "Attempted to reset replacing window on non-existing app token %s",
                     token);
             return;
         }
         if (replacing) {
-            scheduleWindowReplacementTimeouts(appWindowToken);
+            scheduleWindowReplacementTimeouts(activity);
         } else {
-            appWindowToken.clearWillReplaceWindows();
+            activity.clearWillReplaceWindows();
         }
     }
 
-    void scheduleWindowReplacementTimeouts(AppWindowToken appWindowToken) {
-        if (!mWindowReplacementTimeouts.contains(appWindowToken)) {
-            mWindowReplacementTimeouts.add(appWindowToken);
+    void scheduleWindowReplacementTimeouts(ActivityRecord activity) {
+        if (!mWindowReplacementTimeouts.contains(activity)) {
+            mWindowReplacementTimeouts.add(activity);
         }
         mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
         mH.sendEmptyMessageDelayed(
@@ -7312,6 +7313,16 @@
         }
 
         @Override
+        public void hideIme(int displayId) {
+            synchronized (mGlobalLock) {
+                final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                if (dc != null && dc.mInputMethodTarget != null) {
+                    dc.mInputMethodTarget.hideInsets(WindowInsets.Type.ime(), true /* fromIme */);
+                }
+            }
+        }
+
+        @Override
         public boolean isUidAllowedOnDisplay(int displayId, int uid) {
             if (displayId == Display.DEFAULT_DISPLAY) {
                 return true;
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 1c0d156..eb75684 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -773,6 +773,12 @@
 
     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
     public int computeOomAdjFromActivities(int minTaskLayer, ComputeOomAdjCallback callback) {
+        // Since there could be more than one activities in a process record, we don't need to
+        // compute the OomAdj with each of them, just need to find out the activity with the
+        // "best" state, the order would be visible, pausing, stopping...
+        ActivityStack.ActivityState best = DESTROYED;
+        boolean finishing = true;
+        boolean visible = false;
         synchronized (mAtm.mGlobalLockWithoutBoost) {
             final int activitiesSize = mActivities.size();
             for (int j = 0; j < activitiesSize; j++) {
@@ -788,7 +794,6 @@
                     }
                 }
                 if (r.visible) {
-                    callback.onVisibleActivity();
                     final TaskRecord task = r.getTaskRecord();
                     if (task != null && minTaskLayer > 0) {
                         final int layer = task.mLayerRank;
@@ -796,16 +801,32 @@
                             minTaskLayer = layer;
                         }
                     }
-                    break;
-                } else if (r.isState(PAUSING, PAUSED)) {
-                    callback.onPausedActivity();
-                } else if (r.isState(STOPPING)) {
-                    callback.onStoppingActivity(r.finishing);
+                    visible = true;
+                    // continue the loop, in case there are multiple visible activities in
+                    // this process, we'd find out the one with the minimal layer, thus it'll
+                    // get a higher adj score.
                 } else {
-                    callback.onOtherActivity();
+                    if (best != PAUSING && best != PAUSED) {
+                        if (r.isState(PAUSING, PAUSED)) {
+                            best = PAUSING;
+                        } else if (r.isState(STOPPING)) {
+                            best = STOPPING;
+                            // Not "finishing" if any of activity isn't finishing.
+                            finishing &= r.finishing;
+                        }
+                    }
                 }
             }
         }
+        if (visible) {
+            callback.onVisibleActivity();
+        } else if (best == PAUSING) {
+            callback.onPausedActivity();
+        } else if (best == STOPPING) {
+            callback.onStoppingActivity(finishing);
+        } else {
+            callback.onOtherActivity();
+        }
 
         return minTaskLayer;
     }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 40bb059..c25a71d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -249,7 +249,7 @@
     final WindowId mWindowId;
     WindowToken mToken;
     // The same object as mToken if this is an app window and null for non-app windows.
-    AppWindowToken mAppToken;
+    ActivityRecord mActivityRecord;
 
     // mAttrs.flags is tested in animation without being locked. If the bits tested are ever
     // modified they will need to be locked.
@@ -691,7 +691,7 @@
         final boolean immersiveSticky =
                 (mSystemUiVisibility & immersiveStickyFlags) == immersiveStickyFlags;
         return immersiveSticky && mWmService.mSystemGestureExcludedByPreQStickyImmersive
-                && mAppToken != null && mAppToken.mTargetSdk < Build.VERSION_CODES.Q;
+                && mActivityRecord != null && mActivityRecord.mTargetSdk < Build.VERSION_CODES.Q;
     }
 
     void setLastExclusionHeights(int side, int requested, int granted) {
@@ -741,7 +741,7 @@
         mClient = c;
         mAppOp = appOp;
         mToken = token;
-        mAppToken = mToken.asAppWindowToken();
+        mActivityRecord = mToken.asActivityRecord();
         mOwnerUid = ownerId;
         mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
         mWindowId = new WindowId(this);
@@ -805,7 +805,7 @@
         }
         mIsFloatingLayer = mIsImWindow || mIsWallpaper;
 
-        if (mAppToken != null && mAppToken.mShowForAllUsers) {
+        if (mActivityRecord != null && mActivityRecord.mShowForAllUsers) {
             // Windows for apps that can show for all users should also show when the device is
             // locked.
             mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED;
@@ -820,7 +820,8 @@
         mLastRequestedHeight = 0;
         mLayer = 0;
         mInputWindowHandle = new InputWindowHandle(
-                mAppToken != null ? mAppToken.mInputApplicationHandle : null, getDisplayId());
+                mActivityRecord != null ? mActivityRecord.mInputApplicationHandle : null,
+                    getDisplayId());
     }
 
     void attach() {
@@ -835,7 +836,7 @@
      */
     boolean inSizeCompatMode() {
         return (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0
-                || (mAppToken != null && mAppToken.hasSizeCompatBounds()
+                || (mActivityRecord != null && mActivityRecord.hasSizeCompatBounds()
                         // Exclude starting window because it is not displayed by the application.
                         && mAttrs.type != TYPE_APPLICATION_STARTING);
     }
@@ -950,11 +951,11 @@
             layoutYDiff = 0;
         } else {
             mWindowFrames.mContainingFrame.set(getDisplayedBounds());
-            if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) {
+            if (mActivityRecord != null && !mActivityRecord.mFrozenBounds.isEmpty()) {
 
                 // If the bounds are frozen, we still want to translate the window freely and only
                 // freeze the size.
-                Rect frozen = mAppToken.mFrozenBounds.peek();
+                Rect frozen = mActivityRecord.mFrozenBounds.peek();
                 mWindowFrames.mContainingFrame.right =
                         mWindowFrames.mContainingFrame.left + frozen.width();
                 mWindowFrames.mContainingFrame.bottom =
@@ -1137,8 +1138,8 @@
     // TODO: Look into whether this override is still necessary.
     @Override
     public Rect getBounds() {
-        if (mAppToken != null) {
-            return mAppToken.getBounds();
+        if (mActivityRecord != null) {
+            return mActivityRecord.getBounds();
         } else {
             return super.getBounds();
         }
@@ -1239,12 +1240,12 @@
 
     @Override
     public IApplicationToken getAppToken() {
-        return mAppToken != null ? mAppToken.appToken : null;
+        return mActivityRecord != null ? mActivityRecord.appToken : null;
     }
 
     @Override
     public boolean isVoiceInteraction() {
-        return mAppToken != null && mAppToken.mVoiceInteraction;
+        return mActivityRecord != null && mActivityRecord.mVoiceInteraction;
     }
 
     boolean setReportResizeHints() {
@@ -1303,8 +1304,8 @@
 
             // If it's a dead window left on screen, and the configuration changed, there is nothing
             // we can do about it. Remove the window now.
-            if (mAppToken != null && mAppDied) {
-                mAppToken.removeDeadWindows();
+            if (mActivityRecord != null && mAppDied) {
+                mActivityRecord.removeDeadWindows();
                 return;
             }
 
@@ -1328,8 +1329,8 @@
                             this, winAnimator.mSurfaceController);
                 }
                 winAnimator.mDrawState = DRAW_PENDING;
-                if (mAppToken != null) {
-                    mAppToken.clearAllDrawn();
+                if (mActivityRecord != null) {
+                    mActivityRecord.clearAllDrawn();
                 }
             }
             if (!mWmService.mResizingWindows.contains(this)) {
@@ -1401,7 +1402,7 @@
     }
 
     Task getTask() {
-        return mAppToken != null ? mAppToken.getTask() : null;
+        return mActivityRecord != null ? mActivityRecord.getTask() : null;
     }
 
     TaskStack getStack() {
@@ -1450,14 +1451,14 @@
     }
 
     public long getInputDispatchingTimeoutNanos() {
-        return mAppToken != null
-                ? mAppToken.mInputDispatchingTimeoutNanos
+        return mActivityRecord != null
+                ? mActivityRecord.mInputDispatchingTimeoutNanos
                 : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
     }
 
     @Override
     public boolean hasAppShownWindows() {
-        return mAppToken != null && (mAppToken.firstWindowDrawn || mAppToken.startingDisplayed);
+        return mActivityRecord != null && (mActivityRecord.firstWindowDrawn || mActivityRecord.startingDisplayed);
     }
 
     boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
@@ -1537,7 +1538,7 @@
      */
     // TODO: Can we consolidate this with #isVisible() or have a more appropriate name for this?
     boolean isWinVisibleLw() {
-        return (mAppToken == null || !mAppToken.hiddenRequested || mAppToken.isSelfAnimating())
+        return (mActivityRecord == null || !mActivityRecord.hiddenRequested || mActivityRecord.isSelfAnimating())
                 && isVisible();
     }
 
@@ -1565,7 +1566,7 @@
      * call to IWindowSession.add() and the first relayout().
      */
     boolean isVisibleOrAdding() {
-        final AppWindowToken atoken = mAppToken;
+        final ActivityRecord atoken = mActivityRecord;
         return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
                 && isVisibleByPolicy() && !isParentWindowHidden()
                 && (atoken == null || !atoken.hiddenRequested)
@@ -1581,7 +1582,7 @@
         if (!mHasSurface || mDestroying || !isVisibleByPolicy()) {
             return false;
         }
-        final AppWindowToken atoken = mAppToken;
+        final ActivityRecord atoken = mActivityRecord;
         if (atoken != null) {
             return ((!isParentWindowHidden() && !atoken.hiddenRequested)
                     || isAnimating());
@@ -1605,8 +1606,8 @@
      * it must be drawn before allDrawn can become true.
      */
     boolean isInteresting() {
-        return mAppToken != null && !mAppDied
-                && (!mAppToken.isFreezingScreen() || !mAppFreezing)
+        return mActivityRecord != null && !mAppDied
+                && (!mActivityRecord.isFreezingScreen() || !mAppFreezing)
                 && mViewVisibility == View.VISIBLE;
     }
 
@@ -1631,14 +1632,14 @@
         if (translucent) {
             return false;
         }
-        if (mAppToken == null) {
+        if (mActivityRecord == null) {
             final boolean shown = mWinAnimator.getShown();
             final boolean exiting = mAnimatingExit || mDestroying;
             return shown && !exiting;
         } else {
             final Task task = getTask();
             final boolean canFromTask = task != null && task.canAffectSystemUiFlags();
-            return canFromTask && !mAppToken.isHidden();
+            return canFromTask && !mActivityRecord.isHidden();
         }
     }
 
@@ -1648,7 +1649,7 @@
      */
     @Override
     public boolean isDisplayedLw() {
-        final AppWindowToken atoken = mAppToken;
+        final ActivityRecord atoken = mActivityRecord;
         return isDrawnLw() && isVisibleByPolicy()
                 && ((!isParentWindowHidden() && (atoken == null || !atoken.hiddenRequested))
                         || isAnimating());
@@ -1664,7 +1665,7 @@
 
     @Override
     public boolean isGoneForLayoutLw() {
-        final AppWindowToken atoken = mAppToken;
+        final ActivityRecord atoken = mActivityRecord;
         return mViewVisibility == View.GONE
                 || !mRelayoutCalled
                 || (atoken == null && mToken.isHidden())
@@ -1727,7 +1728,7 @@
             // Starting window that's exiting will be removed when the animation finishes.
             // Mark all relevant flags for that onExitAnimationDone will proceed all the way
             // to actually remove it.
-            if (!visible && isVisibleNow() && mAppToken.isSelfAnimating()) {
+            if (!visible && isVisibleNow() && mActivityRecord.isSelfAnimating()) {
                 mAnimatingExit = true;
                 mRemoveOnExit = true;
                 mWindowRemovalAllowed = true;
@@ -2004,8 +2005,8 @@
                             + "callers=%s",
                     this, mWinAnimator.mSurfaceController, mAnimatingExit, mRemoveOnExit,
                     mHasSurface, mWinAnimator.getShown(), isAnimating(),
-                    mAppToken != null && mAppToken.isSelfAnimating(), mWillReplaceWindow,
-                    mAppToken != null && mAppToken.inPendingTransaction,
+                    mActivityRecord != null && mActivityRecord.isSelfAnimating(), mWillReplaceWindow,
+                    mActivityRecord != null && mActivityRecord.inPendingTransaction,
                     mWmService.mDisplayFrozen, Debug.getCallers(6));
 
             // Visibility of the removed window. Will be used later to update orientation later on.
@@ -2064,9 +2065,9 @@
                     }
                 }
                 final boolean isAnimating = isAnimating()
-                        && (mAppToken == null || !mAppToken.isWaitingForTransitionStart());
-                final boolean lastWindowIsStartingWindow = startingWindow && mAppToken != null
-                        && mAppToken.isLastWindow(this);
+                        && (mActivityRecord == null || !mActivityRecord.isWaitingForTransitionStart());
+                final boolean lastWindowIsStartingWindow = startingWindow && mActivityRecord != null
+                        && mActivityRecord.isLastWindow(this);
                 // We delay the removal of a window if it has a showing surface that can be used to run
                 // exit animation and it is marked as exiting.
                 // Also, If isn't the an animating starting window that is the last window in the app.
@@ -2078,8 +2079,8 @@
                     ProtoLog.v(WM_DEBUG_ADD_REMOVE,
                             "Not removing %s due to exit animation", this);
                     setupWindowForRemoveOnExit();
-                    if (mAppToken != null) {
-                        mAppToken.updateReportedVisibilityLocked();
+                    if (mActivityRecord != null) {
+                        mActivityRecord.updateReportedVisibilityLocked();
                     }
                     return;
                 }
@@ -2127,7 +2128,7 @@
             return false;
         }
 
-        final boolean windowsAreFocusable = mAppToken == null || mAppToken.windowsAreFocusable();
+        final boolean windowsAreFocusable = mActivityRecord == null || mActivityRecord.windowsAreFocusable();
         if (!windowsAreFocusable) {
             // This window can't be an IME target if the app's windows should not be focusable.
             return false;
@@ -2160,8 +2161,8 @@
                         + " policyVisAfterAnim=" + mLegacyPolicyVisibilityAfterAnim
                         + " parentHidden=" + isParentWindowHidden()
                         + " exiting=" + mAnimatingExit + " destroying=" + mDestroying);
-                if (mAppToken != null) {
-                    Slog.i(TAG_WM, "  mAppToken.hiddenRequested=" + mAppToken.hiddenRequested);
+                if (mActivityRecord != null) {
+                    Slog.i(TAG_WM, "  mActivityRecord.hiddenRequested=" + mActivityRecord.hiddenRequested);
                 }
             }
         }
@@ -2306,8 +2307,8 @@
         final Region region = inputWindowHandle.touchableRegion;
         setTouchableRegionCropIfNeeded(inputWindowHandle);
 
-        final Rect appOverrideBounds = mAppToken != null
-                ? mAppToken.getResolvedOverrideBounds() : null;
+        final Rect appOverrideBounds = mActivityRecord != null
+                ? mActivityRecord.getResolvedOverrideBounds() : null;
         if (appOverrideBounds != null && !appOverrideBounds.isEmpty()) {
             // There may have touchable letterboxes around the activity, so in order to let the
             // letterboxes are able to receive touch event and slip to activity, the activity with
@@ -2320,22 +2321,22 @@
                 // Non-modal uses the application based frame.
                 mTmpRect.set(mWindowFrames.mCompatFrame);
             }
-            // The offset of compatibility bounds is applied to surface of {@link #AppWindowToken}
+            // The offset of compatibility bounds is applied to surface of {@link #ActivityRecord}
             // and frame, so it is unnecessary to translate twice in surface based coordinates.
-            final int surfaceOffsetX = mAppToken.hasSizeCompatBounds()
-                    ? mAppToken.getBounds().left : 0;
+            final int surfaceOffsetX = mActivityRecord.hasSizeCompatBounds()
+                    ? mActivityRecord.getBounds().left : 0;
             mTmpRect.offset(surfaceOffsetX - mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top);
             region.set(mTmpRect);
             return flags;
         }
 
-        if (modal && mAppToken != null) {
+        if (modal && mActivityRecord != null) {
             // Limit the outer touch to the activity stack region.
             flags |= FLAG_NOT_TOUCH_MODAL;
             // If the inner bounds of letterbox is available, then it will be used as the touchable
             // region so it won't cover the touchable letterbox and the touch events can slip to
             // activity from letterbox.
-            mAppToken.getLetterboxInnerBounds(mTmpRect);
+            mActivityRecord.getLetterboxInnerBounds(mTmpRect);
             if (mTmpRect.isEmpty()) {
                 // If this is a modal window we need to dismiss it if it's not full screen and the
                 // touch happens outside of the frame that displays the content. This means we need
@@ -2426,7 +2427,7 @@
     void prepareWindowToDisplayDuringRelayout(boolean wasVisible) {
         // We need to turn on screen regardless of visibility.
         final boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0
-                || (mAppToken != null && mAppToken.canTurnScreenOn());
+                || (mActivityRecord != null && mActivityRecord.canTurnScreenOn());
 
         // The screen will turn on if the following conditions are met
         // 1. The window has the flag FLAG_TURN_SCREEN_ON or ActivityRecord#canTurnScreenOn.
@@ -2443,7 +2444,7 @@
             boolean allowTheaterMode = mWmService.mAllowTheaterModeWakeFromLayout
                     || Settings.Global.getInt(mWmService.mContext.getContentResolver(),
                             Settings.Global.THEATER_MODE_ON, 0) == 0;
-            boolean canTurnScreenOn = mAppToken == null || mAppToken.currentLaunchCanTurnScreenOn();
+            boolean canTurnScreenOn = mActivityRecord == null || mActivityRecord.currentLaunchCanTurnScreenOn();
 
             if (allowTheaterMode && canTurnScreenOn && !mPowerManagerWrapper.isInteractive()) {
                 if (DEBUG_VISIBILITY || DEBUG_POWER) {
@@ -2453,8 +2454,8 @@
                         PowerManager.WAKE_REASON_APPLICATION, "android.server.wm:SCREEN_ON_FLAG");
             }
 
-            if (mAppToken != null) {
-                mAppToken.setCurrentLaunchCanTurnScreenOn(false);
+            if (mActivityRecord != null) {
+                mActivityRecord.setCurrentLaunchCanTurnScreenOn(false);
             }
         }
 
@@ -2505,14 +2506,14 @@
     }
 
     void adjustStartingWindowFlags() {
-        if (mAttrs.type == TYPE_BASE_APPLICATION && mAppToken != null
-                && mAppToken.startingWindow != null) {
+        if (mAttrs.type == TYPE_BASE_APPLICATION && mActivityRecord != null
+                && mActivityRecord.startingWindow != null) {
             // Special handling of starting window over the base
             // window of the app: propagate lock screen flags to it,
             // to provide the correct semantics while starting.
             final int mask = FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD
                     | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
-            WindowManager.LayoutParams sa = mAppToken.startingWindow.mAttrs;
+            WindowManager.LayoutParams sa = mActivityRecord.startingWindow.mAttrs;
             sa.flags = (sa.flags & ~mask) | (mAttrs.flags & mask);
         }
     }
@@ -2544,8 +2545,8 @@
                     Slog.i(TAG, "WIN DEATH: " + win);
                     if (win != null) {
                         final DisplayContent dc = getDisplayContent();
-                        if (win.mAppToken != null && win.mAppToken.findMainWindow() == win) {
-                            mWmService.mTaskSnapshotController.onAppDied(win.mAppToken);
+                        if (win.mActivityRecord != null && win.mActivityRecord.findMainWindow() == win) {
+                            mWmService.mTaskSnapshotController.onAppDied(win.mActivityRecord);
                         }
                         win.removeIfPossible(shouldKeepVisibleDeadAppWindow());
                         if (win.mAttrs.type == TYPE_DOCK_DIVIDER) {
@@ -2587,7 +2588,7 @@
      * interacts with it.
      */
     private boolean shouldKeepVisibleDeadAppWindow() {
-        if (!isWinVisibleLw() || mAppToken == null || mAppToken.isClientHidden()) {
+        if (!isWinVisibleLw() || mActivityRecord == null || mActivityRecord.isClientHidden()) {
             // Not a visible app window or the app isn't dead.
             return false;
         }
@@ -2612,26 +2613,26 @@
         return isVisibleOrAdding()
                 && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit
                 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
-                && (mAppToken == null || mAppToken.windowsAreFocusable())
+                && (mActivityRecord == null || mActivityRecord.windowsAreFocusable())
                 && !cantReceiveTouchInput();
     }
 
     @Override
     public boolean canShowWhenLocked() {
         final boolean showBecauseOfActivity =
-                mAppToken != null && mAppToken.canShowWhenLocked();
+                mActivityRecord != null && mActivityRecord.canShowWhenLocked();
         final boolean showBecauseOfWindow = (getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0;
         return showBecauseOfActivity || showBecauseOfWindow;
     }
 
     /** @return false if this window desires touch events. */
     boolean cantReceiveTouchInput() {
-        if (mAppToken == null || mAppToken.getTask() == null) {
+        if (mActivityRecord == null || mActivityRecord.getTask() == null) {
             return false;
         }
 
-        return mAppToken.getTask().mStack.shouldIgnoreInput()
-                || mAppToken.hiddenRequested
+        return mActivityRecord.getTask().mStack.shouldIgnoreInput()
+                || mActivityRecord.hiddenRequested
                 || isAnimatingToRecents();
     }
 
@@ -2643,7 +2644,7 @@
                 mWmService.getRecentsAnimationController();
         return recentsAnimationController != null
                 && recentsAnimationController.isAnimatingTask(getTask())
-                && !recentsAnimationController.isTargetApp(mAppToken);
+                && !recentsAnimationController.isTargetApp(mActivityRecord);
     }
 
     @Override
@@ -2883,7 +2884,7 @@
     }
 
     boolean isClosing() {
-        return mAnimatingExit || (mAppToken != null && mAppToken.isClosingOrEnteringPip());
+        return mAnimatingExit || (mActivityRecord != null && mActivityRecord.isClosingOrEnteringPip());
     }
 
     void addWinAnimatorToList(ArrayList<WindowStateAnimator> animators) {
@@ -2898,7 +2899,7 @@
     void sendAppVisibilityToClients() {
         super.sendAppVisibilityToClients();
 
-        final boolean clientHidden = mAppToken.isClientHidden();
+        final boolean clientHidden = mActivityRecord.isClientHidden();
         if (mAttrs.type == TYPE_APPLICATION_STARTING && clientHidden) {
             // Don't hide the starting window.
             return;
@@ -2993,10 +2994,10 @@
             mDestroying = false;
             destroyedSomething = true;
 
-            // Since mDestroying will affect AppWindowToken#allDrawn, we need to perform another
+            // Since mDestroying will affect ActivityRecord#allDrawn, we need to perform another
             // traversal in case we are waiting on this window to start the transition.
             if (getDisplayContent().mAppTransition.isTransitionSet()
-                    && getDisplayContent().mOpeningApps.contains(mAppToken)) {
+                    && getDisplayContent().mOpeningApps.contains(mActivityRecord)) {
                 mWmService.mWindowPlacerLocked.requestTraversal();
             }
         }
@@ -3076,7 +3077,7 @@
         // Child windows are evaluated based on their parent window.
         final WindowState win = getTopParentWindow();
         if (win.mAttrs.type < FIRST_SYSTEM_WINDOW
-                && win.mAppToken != null && win.mAppToken.mShowForAllUsers) {
+                && win.mActivityRecord != null && win.mActivityRecord.mShowForAllUsers) {
 
             // All window frames that are fullscreen extend above status bar, but some don't extend
             // below navigation bar. Thus, check for display frame for top/left and stable frame for
@@ -3216,8 +3217,8 @@
 
     @Override
     public Configuration getConfiguration() {
-        if (mAppToken != null && mAppToken.mFrozenMergedConfig.size() > 0) {
-            return mAppToken.mFrozenMergedConfig.peek();
+        if (mActivityRecord != null && mActivityRecord.mFrozenMergedConfig.size() > 0) {
+            return mActivityRecord.mFrozenMergedConfig.peek();
         }
 
         // If the process has not registered to any display to listen to the configuration change,
@@ -3377,6 +3378,15 @@
         }
     }
 
+    @Override
+    public void hideInsets(@InsetType int types, boolean fromIme) {
+        try {
+            mClient.hideInsets(types, fromIme);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Failed to deliver showInsets", e);
+        }
+    }
+
     Rect getBackdropFrame(Rect frame) {
         // When the task is docked, we send fullscreen sized backDropFrame as soon as resizing
         // start even if we haven't received the relayout window, so that the client requests
@@ -3444,7 +3454,7 @@
 
     /** Is this window in a container that takes up the entire screen space? */
     private boolean inAppWindowThatMatchesParentBounds() {
-        return mAppToken == null || (mAppToken.matchParentBounds() && !inMultiWindowMode());
+        return mActivityRecord == null || (mActivityRecord.matchParentBounds() && !inMultiWindowMode());
     }
 
     /** @return true when the window is in fullscreen mode, but has non-fullscreen bounds set, or
@@ -3456,8 +3466,8 @@
 
     @Override
     public boolean isLetterboxedForDisplayCutoutLw() {
-        if (mAppToken == null) {
-            // Only windows with an AppWindowToken are letterboxed.
+        if (mActivityRecord == null) {
+            // Only windows with an ActivityRecord are letterboxed.
             return false;
         }
         if (!mWindowFrames.parentFrameWasClippedByDisplayCutout()) {
@@ -3482,14 +3492,14 @@
      * @throws NullPointerException if there is no app window token for this window
      */
     private boolean frameCoversEntireAppTokenBounds() {
-        mTmpRect.set(mAppToken.getBounds());
+        mTmpRect.set(mActivityRecord.getBounds());
         mTmpRect.intersectUnchecked(mWindowFrames.mFrame);
-        return mAppToken.getBounds().equals(mTmpRect);
+        return mActivityRecord.getBounds().equals(mTmpRect);
     }
 
     @Override
     public boolean isLetterboxedOverlappingWith(Rect rect) {
-        return mAppToken != null && mAppToken.isLetterboxOverlappingWith(rect);
+        return mActivityRecord != null && mActivityRecord.isLetterboxOverlappingWith(rect);
     }
 
     boolean isDragResizeChanged() {
@@ -3545,7 +3555,7 @@
         // simulate that we are still resizing so the app fills the hole with the resizing
         // background.
         return (getDisplayContent().mDividerControllerLocked.isResizing()
-                        || mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) &&
+                        || mActivityRecord != null && !mActivityRecord.mFrozenBounds.isEmpty()) &&
                 !task.inFreeformWindowingMode() && !isGoneForLayoutLw();
 
     }
@@ -3665,8 +3675,8 @@
         }
         if (dumpAll) {
             pw.println(prefix + "mToken=" + mToken);
-            if (mAppToken != null) {
-                pw.println(prefix + "mAppToken=" + mAppToken);
+            if (mActivityRecord != null) {
+                pw.println(prefix + "mActivityRecord=" + mActivityRecord);
                 pw.print(prefix + "mAppDied=" + mAppDied);
                 pw.print(prefix + "drawnStateEvaluated=" + getDrawnStateEvaluated());
                 pw.println(prefix + "mightAffectAllDrawn=" + mightAffectAllDrawn());
@@ -4068,8 +4078,8 @@
 
     @Override
     public int getRotationAnimationHint() {
-        if (mAppToken != null) {
-            return mAppToken.mRotationAnimationHint;
+        if (mActivityRecord != null) {
+            return mActivityRecord.mRotationAnimationHint;
         } else {
             return -1;
         }
@@ -4092,8 +4102,8 @@
 
         final int drawState = mWinAnimator.mDrawState;
         if ((drawState == HAS_DRAWN || drawState == READY_TO_SHOW)
-                && mAttrs.type != TYPE_APPLICATION_STARTING && mAppToken != null) {
-            mAppToken.onFirstWindowDrawn(this, mWinAnimator);
+                && mAttrs.type != TYPE_APPLICATION_STARTING && mActivityRecord != null) {
+            mActivityRecord.onFirstWindowDrawn(this, mWinAnimator);
         }
 
         if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) {
@@ -4147,11 +4157,11 @@
                     + " during animation: policyVis=" + isVisibleByPolicy()
                     + " parentHidden=" + isParentWindowHidden()
                     + " tok.hiddenRequested="
-                    + (mAppToken != null && mAppToken.hiddenRequested)
-                    + " tok.hidden=" + (mAppToken != null && mAppToken.isHidden())
+                    + (mActivityRecord != null && mActivityRecord.hiddenRequested)
+                    + " tok.hidden=" + (mActivityRecord != null && mActivityRecord.isHidden())
                     + " animating=" + isAnimating()
                     + " tok animating="
-                    + (mAppToken != null && mAppToken.isSelfAnimating())
+                    + (mActivityRecord != null && mActivityRecord.isSelfAnimating())
                     + " Callers=" + Debug.getCallers(4));
         }
     }
@@ -4162,8 +4172,8 @@
         windowInfo.type = mAttrs.type;
         windowInfo.layer = mLayer;
         windowInfo.token = mClient.asBinder();
-        if (mAppToken != null) {
-            windowInfo.activityToken = mAppToken.appToken.asBinder();
+        if (mActivityRecord != null) {
+            windowInfo.activityToken = mActivityRecord.appToken.asBinder();
         }
         windowInfo.title = mAttrs.accessibilityTitle;
         // Panel windows have no public way to set the a11y title directly. Use the
@@ -4393,7 +4403,7 @@
             mWmService.requestTraversal();
             // System windows don't have an activity and an app token as a result, but need a way
             // to be informed about their entrance animation end.
-            if (mAppToken == null) {
+            if (mActivityRecord == null) {
                 try {
                     mClient.dispatchWindowShown();
                 } catch (RemoteException e) {
@@ -4427,8 +4437,8 @@
         // care to ensure the activity has actually stopped and the surface is not still in use.
         // Otherwise we add the service to mDestroySurface and allow it to be processed in our next
         // transaction.
-        if (mAppToken != null) {
-            mAppToken.destroySurfaces();
+        if (mActivityRecord != null) {
+            mActivityRecord.destroySurfaces();
         } else {
             if (hasSurface) {
                 mWmService.mDestroySurface.add(this);
@@ -4555,7 +4565,7 @@
                         + " pv=" + isVisibleByPolicy()
                         + " mDrawState=" + mWinAnimator.mDrawState
                         + " ph=" + isParentWindowHidden()
-                        + " th=" + (mAppToken != null ? mAppToken.hiddenRequested : false)
+                        + " th=" + (mActivityRecord != null ? mActivityRecord.hiddenRequested : false)
                         + " a=" + isAnimating());
             }
         }
@@ -4581,7 +4591,7 @@
         }
 
         // But if we have a frame, and are an application window, then we must be cropped.
-        if (mAppToken != null) {
+        if (mActivityRecord != null) {
             return false;
         }
 
@@ -4896,9 +4906,9 @@
         outMatrix.setValues(float9);
     }
 
-    // TODO: Hack to work around the number of states AppWindowToken needs to access without having
+    // TODO: Hack to work around the number of states ActivityRecord needs to access without having
     // access to its windows children. Need to investigate re-writing
-    // {@link AppWindowToken#updateReportedVisibilityLocked} so this can be removed.
+    // {@link ActivityRecord#updateReportedVisibilityLocked} so this can be removed.
     static final class UpdateReportedVisibilityResults {
         int numInteresting;
         int numVisible;
@@ -4980,9 +4990,9 @@
     boolean needsZBoost() {
         final WindowState inputMethodTarget = getDisplayContent().mInputMethodTarget;
         if (mIsImWindow && inputMethodTarget != null) {
-            final AppWindowToken appToken = inputMethodTarget.mAppToken;
-            if (appToken != null) {
-                return appToken.needsZBoost();
+            final ActivityRecord activity = inputMethodTarget.mActivityRecord;
+            if (activity != null) {
+                return activity.needsZBoost();
             }
         }
         return mWillReplaceWindow;
@@ -5122,7 +5132,7 @@
             if (getParentWindow().isInputMethodTarget()) {
                 return true;
             }
-        } else if (mAppToken != null) {
+        } else if (mActivityRecord != null) {
             // Likewise if we share a token with the Input method target and are ordered
             // above it but not necessarily a child (e.g. a Dialog) then we also need
             // this promotion.
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 1328273..3f25f89 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -266,7 +266,7 @@
         if (DEBUG_ANIM) Slog.v(
                 TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit
                         + ", reportedVisible="
-                        + (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false));
+                        + (mWin.mActivityRecord != null ? mWin.mActivityRecord.reportedVisible : false));
 
         mWin.checkPolicyVisibilityChange();
         final DisplayContent displayContent = mWin.getDisplayContent();
@@ -285,8 +285,8 @@
                     "WindowStateAnimator", displayContent.pendingLayoutChanges);
         }
 
-        if (mWin.mAppToken != null) {
-            mWin.mAppToken.updateReportedVisibilityLocked();
+        if (mWin.mActivityRecord != null) {
+            mWin.mActivityRecord.updateReportedVisibilityLocked();
         }
     }
 
@@ -358,8 +358,8 @@
         }
         mDrawState = READY_TO_SHOW;
         boolean result = false;
-        final AppWindowToken atoken = mWin.mAppToken;
-        if (atoken == null || atoken.canShowWindows()
+        final ActivityRecord activity = mWin.mActivityRecord;
+        if (activity == null || activity.canShowWindows()
                 || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
             result = mWin.performShowLocked();
         }
@@ -409,7 +409,7 @@
                 // we are just doing an in-place switch. In that case any SurfaceFlinger side
                 // child layers need to be reparented to the new surface to make this
                 // transparent to the app.
-                if (mWin.mAppToken == null || mWin.mAppToken.isRelaunching() == false) {
+                if (mWin.mActivityRecord == null || mWin.mActivityRecord.isRelaunching() == false) {
                     mPostDrawTransaction.reparentChildren(mPendingDestroySurface.mSurfaceControl,
                             mSurfaceController.mSurfaceControl)
                             .apply();
@@ -431,16 +431,16 @@
     void resetDrawState() {
         mDrawState = DRAW_PENDING;
 
-        if (mWin.mAppToken == null) {
+        if (mWin.mActivityRecord == null) {
             return;
         }
 
-        if (!mWin.mAppToken.isSelfAnimating()) {
-            mWin.mAppToken.clearAllDrawn();
+        if (!mWin.mActivityRecord.isSelfAnimating()) {
+            mWin.mActivityRecord.clearAllDrawn();
         } else {
             // Currently animating, persist current state of allDrawn until animation
             // is complete.
-            mWin.mAppToken.deferClearAllDrawn = true;
+            mWin.mActivityRecord.deferClearAllDrawn = true;
         }
     }
 
@@ -588,10 +588,10 @@
     }
 
     void destroySurfaceLocked() {
-        final AppWindowToken wtoken = mWin.mAppToken;
-        if (wtoken != null) {
-            if (mWin == wtoken.startingWindow) {
-                wtoken.startingDisplayed = false;
+        final ActivityRecord activity = mWin.mActivityRecord;
+        if (activity != null) {
+            if (mWin == activity.startingWindow) {
+                activity.startingDisplayed = false;
             }
         }
 
@@ -1348,13 +1348,16 @@
         // frozen, there is no reason to animate and it can cause strange
         // artifacts when we unfreeze the display if some different animation
         // is running.
-        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#applyAnimationLocked");
         if (mWin.mToken.okToAnimate()) {
-            int anim = mWin.getDisplayContent().getDisplayPolicy().selectAnimationLw(mWin, transit);
+            int anim = mWin.getDisplayContent().getDisplayPolicy().selectAnimation(mWin, transit);
             int attr = -1;
             Animation a = null;
-            if (anim != 0) {
-                a = anim != -1 ? AnimationUtils.loadAnimation(mContext, anim) : null;
+            if (anim != DisplayPolicy.ANIMATION_STYLEABLE) {
+                if (anim != DisplayPolicy.ANIMATION_NONE) {
+                    Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#loadAnimation");
+                    a = AnimationUtils.loadAnimation(mContext, anim);
+                    Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+                }
             } else {
                 switch (transit) {
                     case WindowManagerPolicy.TRANSIT_ENTER:
@@ -1384,7 +1387,9 @@
                     + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3));
             if (a != null) {
                 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
+                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#startAnimation");
                 mWin.startAnimation(a);
+                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
                 mAnimationIsEntrance = isEntrance;
             }
         } else {
@@ -1395,7 +1400,6 @@
             mWin.getDisplayContent().adjustForImeIfNeeded();
         }
 
-        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
         return mWin.isAnimating();
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 56f6d4b..0cfdebc 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -23,7 +23,6 @@
 import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
 
 import android.os.Debug;
-import android.os.Trace;
 import android.util.Slog;
 
 import java.io.PrintWriter;
@@ -52,15 +51,19 @@
     /** The number of layout requests when deferring. */
     private int mDeferredRequests;
 
-    private final Runnable mPerformSurfacePlacement;
-
-    public WindowSurfacePlacer(WindowManagerService service) {
-        mService = service;
-        mPerformSurfacePlacement = () -> {
+    private class Traverser implements Runnable {
+        @Override
+        public void run() {
             synchronized (mService.mGlobalLock) {
                 performSurfacePlacement();
             }
-        };
+        }
+    }
+
+    private final Traverser mPerformSurfacePlacement = new Traverser();
+
+    WindowSurfacePlacer(WindowManagerService service) {
+        mService = service;
     }
 
     /**
@@ -152,7 +155,6 @@
             return;
         }
 
-        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
         mInLayout = true;
 
         boolean recoveringMemory = false;
@@ -198,8 +200,6 @@
             mInLayout = false;
             Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
         }
-
-        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
     }
 
     void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 5b362c3..ad71237 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -243,7 +243,7 @@
         return false;
     }
 
-    AppWindowToken asAppWindowToken() {
+    ActivityRecord asActivityRecord() {
         // TODO: Not sure if this is the best way to handle this vs. using instanceof and casting.
         // I am not an app window token!
         return null;
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index fb2fdab..dd2629d 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -201,8 +201,7 @@
 
     void setDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray);
 
-    status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
-            int32_t displayId);
+    status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
     status_t registerInputMonitor(JNIEnv* env, const sp<InputChannel>& inputChannel,
             int32_t displayId, bool isGestureMonitor);
     status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
@@ -435,10 +434,9 @@
 }
 
 status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
-        const sp<InputChannel>& inputChannel, int32_t displayId) {
+        const sp<InputChannel>& inputChannel) {
     ATRACE_CALL();
-    return mInputManager->getDispatcher()->registerInputChannel(
-            inputChannel, displayId);
+    return mInputManager->getDispatcher()->registerInputChannel(inputChannel);
 }
 
 status_t NativeInputManager::registerInputMonitor(JNIEnv* /* env */,
@@ -1405,7 +1403,7 @@
 }
 
 static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
-        jlong ptr, jobject inputChannelObj, jint displayId) {
+        jlong ptr, jobject inputChannelObj) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
@@ -1415,7 +1413,7 @@
         return;
     }
 
-    status_t status = im->registerInputChannel(env, inputChannel, displayId);
+    status_t status = im->registerInputChannel(env, inputChannel);
 
     if (status) {
         std::string message;
@@ -1757,7 +1755,7 @@
     { "nativeHasKeys", "(JII[I[Z)Z",
             (void*) nativeHasKeys },
     { "nativeRegisterInputChannel",
-            "(JLandroid/view/InputChannel;I)V",
+            "(JLandroid/view/InputChannel;)V",
             (void*) nativeRegisterInputChannel },
     { "nativeRegisterInputMonitor",
             "(JLandroid/view/InputChannel;IZ)V",
diff --git a/services/core/jni/com_android_server_security_VerityUtils.cpp b/services/core/jni/com_android_server_security_VerityUtils.cpp
index 9ceb770..906b568 100644
--- a/services/core/jni/com_android_server_security_VerityUtils.cpp
+++ b/services/core/jni/com_android_server_security_VerityUtils.cpp
@@ -17,6 +17,8 @@
 #define LOG_TAG "VerityUtils"
 
 #include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
 #include "jni.h"
 #include <utils/Log.h>
 
@@ -72,11 +74,17 @@
 namespace {
 
 int enableFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath, jbyteArray signature) {
-    const char* path = env->GetStringUTFChars(filePath, nullptr);
-    ::android::base::unique_fd rfd(open(path, O_RDONLY | O_CLOEXEC));
-    env->ReleaseStringUTFChars(filePath, path);
+    ScopedUtfChars path(env, filePath);
+    if (path.c_str() == nullptr) {
+        return EINVAL;
+    }
+    ::android::base::unique_fd rfd(open(path.c_str(), O_RDONLY | O_CLOEXEC));
     if (rfd.get() < 0) {
-      return errno;
+        return errno;
+    }
+    ScopedByteArrayRO signature_bytes(env, signature);
+    if (signature_bytes.get() == nullptr) {
+        return EINVAL;
     }
 
     fsverity_enable_arg arg = {};
@@ -85,11 +93,11 @@
     arg.block_size = 4096;
     arg.salt_size = 0;
     arg.salt_ptr = reinterpret_cast<uintptr_t>(nullptr);
-    arg.sig_size = env->GetArrayLength(signature);
-    arg.sig_ptr = reinterpret_cast<uintptr_t>(signature);
+    arg.sig_size = signature_bytes.size();
+    arg.sig_ptr = reinterpret_cast<uintptr_t>(signature_bytes.get());
 
     if (ioctl(rfd.get(), FS_IOC_ENABLE_VERITY, &arg) < 0) {
-      return errno;
+        return errno;
     }
     return 0;
 }
@@ -101,14 +109,16 @@
     fsverity_digest *data = reinterpret_cast<fsverity_digest *>(&bytes);
     data->digest_size = kSha256Bytes;  // the only input/output parameter
 
-    const char* path = env->GetStringUTFChars(filePath, nullptr);
-    ::android::base::unique_fd rfd(open(path, O_RDONLY | O_CLOEXEC));
-    env->ReleaseStringUTFChars(filePath, path);
+    ScopedUtfChars path(env, filePath);
+    if (path.c_str() == nullptr) {
+        return EINVAL;
+    }
+    ::android::base::unique_fd rfd(open(path.c_str(), O_RDONLY | O_CLOEXEC));
     if (rfd.get() < 0) {
-      return errno;
+        return errno;
     }
     if (ioctl(rfd.get(), FS_IOC_MEASURE_VERITY, data) < 0) {
-      return errno;
+        return errno;
     }
     return 0;
 }
diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp
index 47790ce..91c05a8 100644
--- a/services/devicepolicy/Android.bp
+++ b/services/devicepolicy/Android.bp
@@ -5,4 +5,13 @@
     libs: [
         "services.core",
     ],
+
+    plugins: [
+        "compat-changeid-annotation-processor",
+    ],
 }
+
+platform_compat_config {
+    name: "services-devicepolicy-platform-compat-config",
+    src: ":services.devicepolicy",
+}
\ No newline at end of file
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9569ac8..6f643c9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -129,6 +129,7 @@
 import android.app.admin.DeviceStateCache;
 import android.app.admin.NetworkEvent;
 import android.app.admin.PasswordMetrics;
+import android.app.admin.PasswordPolicy;
 import android.app.admin.SecurityLog;
 import android.app.admin.SecurityLog.SecurityEvent;
 import android.app.admin.StartInstallingUpdateCallback;
@@ -137,6 +138,8 @@
 import android.app.backup.IBackupManager;
 import android.app.trust.TrustManager;
 import android.app.usage.UsageStatsManagerInternal;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -235,6 +238,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.IPlatformCompat;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
@@ -251,6 +255,8 @@
 import com.android.internal.util.XmlUtils;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockSettingsInternal;
+import com.android.internal.widget.LockscreenCredential;
+import com.android.internal.widget.PasswordValidationError;
 import com.android.server.LocalServices;
 import com.android.server.LockGuard;
 import com.android.server.SystemServerInitThreadPool;
@@ -494,6 +500,22 @@
     private static final String LOG_TAG_PROFILE_OWNER = "profile-owner";
     private static final String LOG_TAG_DEVICE_OWNER = "device-owner";
 
+    /**
+     * For admin apps targeting R+, throw when the app sets password requirement
+     * that is not taken into account at given quality. For example when quality is set
+     * to {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, it doesn't make sense to
+     * require certain password length. If the intent is to require a password of certain length
+     * having at least NUMERIC quality, the admin should first call
+     * {@link #setPasswordQuality(ComponentName, int, boolean)} and only then call
+     * {@link #setPasswordMinimumLength(ComponentName, int, boolean)}.
+     *
+     * <p>Conversely when an admin app targeting R+ lowers password quality, those
+     * requirements that stop making sense are reset to default values.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
+    private static final long ADMIN_APP_PASSWORD_COMPLEXITY = 123562444L;
+
     final Context mContext;
     final Injector mInjector;
     final IPackageManager mIPackageManager;
@@ -506,6 +528,7 @@
     private final LockSettingsInternal mLockSettingsInternal;
     private final DeviceAdminServiceController mDeviceAdminServiceController;
     private final OverlayPackagesProvider mOverlayPackagesProvider;
+    private final IPlatformCompat mIPlatformCompat;
 
     private final DevicePolicyCacheImpl mPolicyCache = new DevicePolicyCacheImpl();
     private final DeviceStateCacheImpl mStateCache = new DeviceStateCacheImpl();
@@ -968,19 +991,8 @@
         static final int DEF_PASSWORD_HISTORY_LENGTH = 0;
         int passwordHistoryLength = DEF_PASSWORD_HISTORY_LENGTH;
 
-        static final int DEF_MINIMUM_PASSWORD_LENGTH = 0;
-        static final int DEF_MINIMUM_PASSWORD_LETTERS = 1;
-        static final int DEF_MINIMUM_PASSWORD_UPPER_CASE = 0;
-        static final int DEF_MINIMUM_PASSWORD_LOWER_CASE = 0;
-        static final int DEF_MINIMUM_PASSWORD_NUMERIC = 1;
-        static final int DEF_MINIMUM_PASSWORD_SYMBOLS = 1;
-        static final int DEF_MINIMUM_PASSWORD_NON_LETTER = 0;
         @NonNull
-        PasswordMetrics minimumPasswordMetrics = new PasswordMetrics(
-                PASSWORD_QUALITY_UNSPECIFIED, DEF_MINIMUM_PASSWORD_LENGTH,
-                DEF_MINIMUM_PASSWORD_LETTERS, DEF_MINIMUM_PASSWORD_UPPER_CASE,
-                DEF_MINIMUM_PASSWORD_LOWER_CASE, DEF_MINIMUM_PASSWORD_NUMERIC,
-                DEF_MINIMUM_PASSWORD_SYMBOLS, DEF_MINIMUM_PASSWORD_NON_LETTER);
+        PasswordPolicy mPasswordPolicy = new PasswordPolicy();
 
         static final long DEF_MAXIMUM_TIME_TO_UNLOCK = 0;
         long maximumTimeToUnlock = DEF_MAXIMUM_TIME_TO_UNLOCK;
@@ -1115,36 +1127,36 @@
             out.startTag(null, TAG_POLICIES);
             info.writePoliciesToXml(out);
             out.endTag(null, TAG_POLICIES);
-            if (minimumPasswordMetrics.quality != PASSWORD_QUALITY_UNSPECIFIED) {
+            if (mPasswordPolicy.quality != PASSWORD_QUALITY_UNSPECIFIED) {
                 writeAttributeValueToXml(
-                        out, TAG_PASSWORD_QUALITY, minimumPasswordMetrics.quality);
-                if (minimumPasswordMetrics.length != DEF_MINIMUM_PASSWORD_LENGTH) {
+                        out, TAG_PASSWORD_QUALITY, mPasswordPolicy.quality);
+                if (mPasswordPolicy.length != PasswordPolicy.DEF_MINIMUM_LENGTH) {
                     writeAttributeValueToXml(
-                            out, TAG_MIN_PASSWORD_LENGTH, minimumPasswordMetrics.length);
+                            out, TAG_MIN_PASSWORD_LENGTH, mPasswordPolicy.length);
                 }
-                if (minimumPasswordMetrics.upperCase != DEF_MINIMUM_PASSWORD_UPPER_CASE) {
+                if (mPasswordPolicy.upperCase != PasswordPolicy.DEF_MINIMUM_UPPER_CASE) {
                     writeAttributeValueToXml(
-                            out, TAG_MIN_PASSWORD_UPPERCASE, minimumPasswordMetrics.upperCase);
+                            out, TAG_MIN_PASSWORD_UPPERCASE, mPasswordPolicy.upperCase);
                 }
-                if (minimumPasswordMetrics.lowerCase != DEF_MINIMUM_PASSWORD_LOWER_CASE) {
+                if (mPasswordPolicy.lowerCase != PasswordPolicy.DEF_MINIMUM_LOWER_CASE) {
                     writeAttributeValueToXml(
-                            out, TAG_MIN_PASSWORD_LOWERCASE, minimumPasswordMetrics.lowerCase);
+                            out, TAG_MIN_PASSWORD_LOWERCASE, mPasswordPolicy.lowerCase);
                 }
-                if (minimumPasswordMetrics.letters != DEF_MINIMUM_PASSWORD_LETTERS) {
+                if (mPasswordPolicy.letters != PasswordPolicy.DEF_MINIMUM_LETTERS) {
                     writeAttributeValueToXml(
-                            out, TAG_MIN_PASSWORD_LETTERS, minimumPasswordMetrics.letters);
+                            out, TAG_MIN_PASSWORD_LETTERS, mPasswordPolicy.letters);
                 }
-                if (minimumPasswordMetrics.numeric != DEF_MINIMUM_PASSWORD_NUMERIC) {
+                if (mPasswordPolicy.numeric != PasswordPolicy.DEF_MINIMUM_NUMERIC) {
                     writeAttributeValueToXml(
-                            out, TAG_MIN_PASSWORD_NUMERIC, minimumPasswordMetrics.numeric);
+                            out, TAG_MIN_PASSWORD_NUMERIC, mPasswordPolicy.numeric);
                 }
-                if (minimumPasswordMetrics.symbols != DEF_MINIMUM_PASSWORD_SYMBOLS) {
+                if (mPasswordPolicy.symbols != PasswordPolicy.DEF_MINIMUM_SYMBOLS) {
                     writeAttributeValueToXml(
-                            out, TAG_MIN_PASSWORD_SYMBOLS, minimumPasswordMetrics.symbols);
+                            out, TAG_MIN_PASSWORD_SYMBOLS, mPasswordPolicy.symbols);
                 }
-                if (minimumPasswordMetrics.nonLetter > DEF_MINIMUM_PASSWORD_NON_LETTER) {
+                if (mPasswordPolicy.nonLetter > PasswordPolicy.DEF_MINIMUM_NON_LETTER) {
                     writeAttributeValueToXml(
-                            out, TAG_MIN_PASSWORD_NONLETTER, minimumPasswordMetrics.nonLetter);
+                            out, TAG_MIN_PASSWORD_NONLETTER, mPasswordPolicy.nonLetter);
                 }
             }
             if (passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) {
@@ -1383,31 +1395,31 @@
                         info.readPoliciesFromXml(parser);
                     }
                 } else if (TAG_PASSWORD_QUALITY.equals(tag)) {
-                    minimumPasswordMetrics.quality = Integer.parseInt(
+                    mPasswordPolicy.quality = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_MIN_PASSWORD_LENGTH.equals(tag)) {
-                    minimumPasswordMetrics.length = Integer.parseInt(
+                    mPasswordPolicy.length = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_PASSWORD_HISTORY_LENGTH.equals(tag)) {
                     passwordHistoryLength = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_MIN_PASSWORD_UPPERCASE.equals(tag)) {
-                    minimumPasswordMetrics.upperCase = Integer.parseInt(
+                    mPasswordPolicy.upperCase = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_MIN_PASSWORD_LOWERCASE.equals(tag)) {
-                    minimumPasswordMetrics.lowerCase = Integer.parseInt(
+                    mPasswordPolicy.lowerCase = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_MIN_PASSWORD_LETTERS.equals(tag)) {
-                    minimumPasswordMetrics.letters = Integer.parseInt(
+                    mPasswordPolicy.letters = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_MIN_PASSWORD_NUMERIC.equals(tag)) {
-                    minimumPasswordMetrics.numeric = Integer.parseInt(
+                    mPasswordPolicy.numeric = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_MIN_PASSWORD_SYMBOLS.equals(tag)) {
-                    minimumPasswordMetrics.symbols = Integer.parseInt(
+                    mPasswordPolicy.symbols = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_MIN_PASSWORD_NONLETTER.equals(tag)) {
-                    minimumPasswordMetrics.nonLetter = Integer.parseInt(
+                    mPasswordPolicy.nonLetter = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
                 }else if (TAG_MAX_TIME_TO_UNLOCK.equals(tag)) {
                     maximumTimeToUnlock = Long.parseLong(
@@ -1668,23 +1680,23 @@
                 pw.decreaseIndent();
             }
             pw.print("passwordQuality=0x");
-                    pw.println(Integer.toHexString(minimumPasswordMetrics.quality));
+                    pw.println(Integer.toHexString(mPasswordPolicy.quality));
             pw.print("minimumPasswordLength=");
-                    pw.println(minimumPasswordMetrics.length);
+                    pw.println(mPasswordPolicy.length);
             pw.print("passwordHistoryLength=");
                     pw.println(passwordHistoryLength);
             pw.print("minimumPasswordUpperCase=");
-                    pw.println(minimumPasswordMetrics.upperCase);
+                    pw.println(mPasswordPolicy.upperCase);
             pw.print("minimumPasswordLowerCase=");
-                    pw.println(minimumPasswordMetrics.lowerCase);
+                    pw.println(mPasswordPolicy.lowerCase);
             pw.print("minimumPasswordLetters=");
-                    pw.println(minimumPasswordMetrics.letters);
+                    pw.println(mPasswordPolicy.letters);
             pw.print("minimumPasswordNumeric=");
-                    pw.println(minimumPasswordMetrics.numeric);
+                    pw.println(mPasswordPolicy.numeric);
             pw.print("minimumPasswordSymbols=");
-                    pw.println(minimumPasswordMetrics.symbols);
+                    pw.println(mPasswordPolicy.symbols);
             pw.print("minimumPasswordNonLetter=");
-                    pw.println(minimumPasswordMetrics.nonLetter);
+                    pw.println(mPasswordPolicy.nonLetter);
             pw.print("maximumTimeToUnlock=");
                     pw.println(maximumTimeToUnlock);
             pw.print("strongAuthUnlockTimeout=");
@@ -1984,6 +1996,11 @@
             return LocalServices.getService(LockSettingsInternal.class);
         }
 
+        IPlatformCompat getIPlatformCompat() {
+            return IPlatformCompat.Stub.asInterface(
+                    ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+        }
+
         boolean hasUserSetupCompleted(DevicePolicyData userData) {
             return userData.mUserSetupComplete;
         }
@@ -2222,6 +2239,7 @@
         mUsageStatsManagerInternal = Preconditions.checkNotNull(
                 injector.getUsageStatsManagerInternal());
         mIPackageManager = Preconditions.checkNotNull(injector.getIPackageManager());
+        mIPlatformCompat = Preconditions.checkNotNull(injector.getIPlatformCompat());
         mIPermissionManager = Preconditions.checkNotNull(injector.getIPermissionManager());
         mTelephonyManager = Preconditions.checkNotNull(injector.getTelephonyManager());
 
@@ -4135,15 +4153,15 @@
                     who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
             final long ident = mInjector.binderClearCallingIdentity();
             try {
-                final PasswordMetrics metrics = ap.minimumPasswordMetrics;
-                if (metrics.quality != quality) {
-                    metrics.quality = quality;
+                final PasswordPolicy passwordPolicy = ap.mPasswordPolicy;
+                if (passwordPolicy.quality != quality) {
+                    passwordPolicy.quality = quality;
                     resetInactivePasswordRequirementsIfRPlus(userId, ap);
                     updatePasswordValidityCheckpointLocked(userId, parent);
                     updatePasswordQualityCacheForUserGroup(userId);
                     saveSettingsLocked(userId);
                 }
-                maybeLogPasswordComplexitySet(who, userId, parent, metrics);
+                maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
             } finally {
                 mInjector.binderRestoreCallingIdentity(ident);
             }
@@ -4156,23 +4174,33 @@
                 .write();
     }
 
+    private boolean passwordQualityInvocationOrderCheckEnabled(String packageName, int userId) {
+        try {
+            return mIPlatformCompat.isChangeEnabledByPackageName(ADMIN_APP_PASSWORD_COMPLEXITY,
+                    packageName);
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, "Failed to get a response from PLATFORM_COMPAT_SERVICE", e);
+        }
+        return getTargetSdk(packageName, userId) > Build.VERSION_CODES.Q;
+    }
+
     /**
      * For admins targeting R+ reset various password constraints to default values when quality is
      * set to a value that makes those constraints that have no effect.
      */
     private void resetInactivePasswordRequirementsIfRPlus(int userId, ActiveAdmin admin) {
-        if (getTargetSdk(admin.info.getPackageName(), userId) > Build.VERSION_CODES.Q) {
-            final PasswordMetrics metrics = admin.minimumPasswordMetrics;
-            if (metrics.quality < PASSWORD_QUALITY_NUMERIC) {
-                metrics.length = ActiveAdmin.DEF_MINIMUM_PASSWORD_LENGTH;
+        if (passwordQualityInvocationOrderCheckEnabled(admin.info.getPackageName(), userId)) {
+            final PasswordPolicy policy = admin.mPasswordPolicy;
+            if (policy.quality < PASSWORD_QUALITY_NUMERIC) {
+                policy.length = PasswordPolicy.DEF_MINIMUM_LENGTH;
             }
-            if (metrics.quality < PASSWORD_QUALITY_COMPLEX) {
-                metrics.letters = ActiveAdmin.DEF_MINIMUM_PASSWORD_LETTERS;
-                metrics.upperCase = ActiveAdmin.DEF_MINIMUM_PASSWORD_UPPER_CASE;
-                metrics.lowerCase = ActiveAdmin.DEF_MINIMUM_PASSWORD_LOWER_CASE;
-                metrics.numeric = ActiveAdmin.DEF_MINIMUM_PASSWORD_NUMERIC;
-                metrics.symbols = ActiveAdmin.DEF_MINIMUM_PASSWORD_SYMBOLS;
-                metrics.nonLetter = ActiveAdmin.DEF_MINIMUM_PASSWORD_NON_LETTER;
+            if (policy.quality < PASSWORD_QUALITY_COMPLEX) {
+                policy.letters = PasswordPolicy.DEF_MINIMUM_LETTERS;
+                policy.upperCase = PasswordPolicy.DEF_MINIMUM_UPPER_CASE;
+                policy.lowerCase = PasswordPolicy.DEF_MINIMUM_LOWER_CASE;
+                policy.numeric = PasswordPolicy.DEF_MINIMUM_NUMERIC;
+                policy.symbols = PasswordPolicy.DEF_MINIMUM_SYMBOLS;
+                policy.nonLetter = PasswordPolicy.DEF_MINIMUM_NON_LETTER;
             }
         }
     }
@@ -4237,7 +4265,7 @@
 
             if (who != null) {
                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent);
-                return admin != null ? admin.minimumPasswordMetrics.quality : mode;
+                return admin != null ? admin.mPasswordPolicy.quality : mode;
             }
 
             // Return the strictest policy across all participating admins.
@@ -4246,8 +4274,8 @@
             final int N = admins.size();
             for (int i = 0; i < N; i++) {
                 ActiveAdmin admin = admins.get(i);
-                if (mode < admin.minimumPasswordMetrics.quality) {
-                    mode = admin.minimumPasswordMetrics.quality;
+                if (mode < admin.mPasswordPolicy.quality) {
+                    mode = admin.mPasswordPolicy.quality;
                 }
             }
             return mode;
@@ -4307,14 +4335,14 @@
         synchronized (getLockObject()) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(
                     who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
-            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
             ensureMinimumQuality(userId, ap, PASSWORD_QUALITY_NUMERIC, "setPasswordMinimumLength");
-            if (metrics.length != length) {
-                metrics.length = length;
+            final PasswordPolicy passwordPolicy = ap.mPasswordPolicy;
+            if (passwordPolicy.length != length) {
+                passwordPolicy.length = length;
                 updatePasswordValidityCheckpointLocked(userId, parent);
                 saveSettingsLocked(userId);
             }
-            maybeLogPasswordComplexitySet(who, userId, parent, metrics);
+            maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_LENGTH)
@@ -4325,8 +4353,9 @@
 
     private void ensureMinimumQuality(
             int userId, ActiveAdmin admin, int minimumQuality, String operation) {
-        if (admin.minimumPasswordMetrics.quality < minimumQuality
-                && getTargetSdk(admin.info.getPackageName(), userId) > Build.VERSION_CODES.Q) {
+        if (admin.mPasswordPolicy.quality < minimumQuality
+                && passwordQualityInvocationOrderCheckEnabled(admin.info.getPackageName(),
+                userId)) {
             throw new IllegalStateException(String.format(
                     "password quality should be at least %d for %s", minimumQuality, operation));
         }
@@ -4335,7 +4364,7 @@
     @Override
     public int getPasswordMinimumLength(ComponentName who, int userHandle, boolean parent) {
         return getStrictestPasswordRequirement(who, userHandle, parent,
-                admin -> admin.minimumPasswordMetrics.length, PASSWORD_QUALITY_NUMERIC);
+                admin -> admin.mPasswordPolicy.length, PASSWORD_QUALITY_NUMERIC);
     }
 
     @Override
@@ -4564,13 +4593,13 @@
                     who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
             ensureMinimumQuality(
                     userId, ap, PASSWORD_QUALITY_COMPLEX, "setPasswordMinimumUpperCase");
-            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
-            if (metrics.upperCase != length) {
-                metrics.upperCase = length;
+            final PasswordPolicy passwordPolicy = ap.mPasswordPolicy;
+            if (passwordPolicy.upperCase != length) {
+                passwordPolicy.upperCase = length;
                 updatePasswordValidityCheckpointLocked(userId, parent);
                 saveSettingsLocked(userId);
             }
-            maybeLogPasswordComplexitySet(who, userId, parent, metrics);
+            maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_UPPER_CASE)
@@ -4582,7 +4611,7 @@
     @Override
     public int getPasswordMinimumUpperCase(ComponentName who, int userHandle, boolean parent) {
         return getStrictestPasswordRequirement(who, userHandle, parent,
-                admin -> admin.minimumPasswordMetrics.upperCase, PASSWORD_QUALITY_COMPLEX);
+                admin -> admin.mPasswordPolicy.upperCase, PASSWORD_QUALITY_COMPLEX);
     }
 
     @Override
@@ -4594,13 +4623,13 @@
                     who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
             ensureMinimumQuality(
                     userId, ap, PASSWORD_QUALITY_COMPLEX, "setPasswordMinimumLowerCase");
-            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
-            if (metrics.lowerCase != length) {
-                metrics.lowerCase = length;
+            final PasswordPolicy passwordPolicy = ap.mPasswordPolicy;
+            if (passwordPolicy.lowerCase != length) {
+                passwordPolicy.lowerCase = length;
                 updatePasswordValidityCheckpointLocked(userId, parent);
                 saveSettingsLocked(userId);
             }
-            maybeLogPasswordComplexitySet(who, userId, parent, metrics);
+            maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_LOWER_CASE)
@@ -4612,7 +4641,7 @@
     @Override
     public int getPasswordMinimumLowerCase(ComponentName who, int userHandle, boolean parent) {
         return getStrictestPasswordRequirement(who, userHandle, parent,
-                admin -> admin.minimumPasswordMetrics.lowerCase, PASSWORD_QUALITY_COMPLEX);
+                admin -> admin.mPasswordPolicy.lowerCase, PASSWORD_QUALITY_COMPLEX);
     }
 
     @Override
@@ -4626,13 +4655,13 @@
             ActiveAdmin ap = getActiveAdminForCallerLocked(
                     who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
             ensureMinimumQuality(userId, ap, PASSWORD_QUALITY_COMPLEX, "setPasswordMinimumLetters");
-            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
-            if (metrics.letters != length) {
-                metrics.letters = length;
+            final PasswordPolicy passwordPolicy = ap.mPasswordPolicy;
+            if (passwordPolicy.letters != length) {
+                passwordPolicy.letters = length;
                 updatePasswordValidityCheckpointLocked(userId, parent);
                 saveSettingsLocked(userId);
             }
-            maybeLogPasswordComplexitySet(who, userId, parent, metrics);
+            maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_LETTERS)
@@ -4644,7 +4673,7 @@
     @Override
     public int getPasswordMinimumLetters(ComponentName who, int userHandle, boolean parent) {
         return getStrictestPasswordRequirement(who, userHandle, parent,
-                admin -> admin.minimumPasswordMetrics.letters, PASSWORD_QUALITY_COMPLEX);
+                admin -> admin.mPasswordPolicy.letters, PASSWORD_QUALITY_COMPLEX);
     }
 
     @Override
@@ -4658,13 +4687,13 @@
             ActiveAdmin ap = getActiveAdminForCallerLocked(
                     who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
             ensureMinimumQuality(userId, ap, PASSWORD_QUALITY_COMPLEX, "setPasswordMinimumNumeric");
-            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
-            if (metrics.numeric != length) {
-                metrics.numeric = length;
+            final PasswordPolicy passwordPolicy = ap.mPasswordPolicy;
+            if (passwordPolicy.numeric != length) {
+                passwordPolicy.numeric = length;
                 updatePasswordValidityCheckpointLocked(userId, parent);
                 saveSettingsLocked(userId);
             }
-            maybeLogPasswordComplexitySet(who, userId, parent, metrics);
+            maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_NUMERIC)
@@ -4676,7 +4705,7 @@
     @Override
     public int getPasswordMinimumNumeric(ComponentName who, int userHandle, boolean parent) {
         return getStrictestPasswordRequirement(who, userHandle, parent,
-                admin -> admin.minimumPasswordMetrics.numeric, PASSWORD_QUALITY_COMPLEX);
+                admin -> admin.mPasswordPolicy.numeric, PASSWORD_QUALITY_COMPLEX);
     }
 
     @Override
@@ -4690,13 +4719,13 @@
             ActiveAdmin ap = getActiveAdminForCallerLocked(
                     who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
             ensureMinimumQuality(userId, ap, PASSWORD_QUALITY_COMPLEX, "setPasswordMinimumSymbols");
-            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
-            if (metrics.symbols != length) {
-                ap.minimumPasswordMetrics.symbols = length;
+            final PasswordPolicy passwordPolicy = ap.mPasswordPolicy;
+            if (passwordPolicy.symbols != length) {
+                ap.mPasswordPolicy.symbols = length;
                 updatePasswordValidityCheckpointLocked(userId, parent);
                 saveSettingsLocked(userId);
             }
-            maybeLogPasswordComplexitySet(who, userId, parent, metrics);
+            maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_SYMBOLS)
@@ -4708,7 +4737,7 @@
     @Override
     public int getPasswordMinimumSymbols(ComponentName who, int userHandle, boolean parent) {
         return getStrictestPasswordRequirement(who, userHandle, parent,
-                admin -> admin.minimumPasswordMetrics.symbols, PASSWORD_QUALITY_COMPLEX);
+                admin -> admin.mPasswordPolicy.symbols, PASSWORD_QUALITY_COMPLEX);
     }
 
     @Override
@@ -4723,13 +4752,13 @@
                     who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
             ensureMinimumQuality(
                     userId, ap, PASSWORD_QUALITY_COMPLEX, "setPasswordMinimumNonLetter");
-            final PasswordMetrics metrics = ap.minimumPasswordMetrics;
-            if (metrics.nonLetter != length) {
-                ap.minimumPasswordMetrics.nonLetter = length;
+            final PasswordPolicy passwordPolicy = ap.mPasswordPolicy;
+            if (passwordPolicy.nonLetter != length) {
+                ap.mPasswordPolicy.nonLetter = length;
                 updatePasswordValidityCheckpointLocked(userId, parent);
                 saveSettingsLocked(userId);
             }
-            maybeLogPasswordComplexitySet(who, userId, parent, metrics);
+            maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_NON_LETTER)
@@ -4741,7 +4770,7 @@
     @Override
     public int getPasswordMinimumNonLetter(ComponentName who, int userHandle, boolean parent) {
         return getStrictestPasswordRequirement(who, userHandle, parent,
-                admin -> admin.minimumPasswordMetrics.nonLetter, PASSWORD_QUALITY_COMPLEX);
+                admin -> admin.mPasswordPolicy.nonLetter, PASSWORD_QUALITY_COMPLEX);
     }
 
     /**
@@ -4777,6 +4806,33 @@
         }
     }
 
+    /**
+     * Calculates strictest (maximum) value for a given password property enforced by admin[s].
+     */
+    @Override
+    public PasswordMetrics getPasswordMinimumMetrics(@UserIdInt int userHandle) {
+        return getPasswordMinimumMetrics(userHandle, false /* parent */);
+    }
+
+    /**
+     * Calculates strictest (maximum) value for a given password property enforced by admin[s].
+     */
+    private PasswordMetrics getPasswordMinimumMetrics(@UserIdInt int userHandle, boolean parent) {
+        if (!mHasFeature) {
+            new PasswordMetrics(LockPatternUtils.CREDENTIAL_TYPE_NONE);
+        }
+        enforceFullCrossUsersPermission(userHandle);
+        ArrayList<PasswordMetrics> adminMetrics = new ArrayList<>();
+        synchronized (getLockObject()) {
+            List<ActiveAdmin> admins =
+                    getActiveAdminsForLockscreenPoliciesLocked(userHandle, parent);
+            for (ActiveAdmin admin : admins) {
+                adminMetrics.add(admin.mPasswordPolicy.getMinMetrics());
+            }
+        }
+        return PasswordMetrics.merge(adminMetrics);
+    }
+
     @Override
     public boolean isActivePasswordSufficient(int userHandle, boolean parent) {
         if (!mHasFeature) {
@@ -4792,8 +4848,9 @@
             int credentialOwner = getCredentialOwner(userHandle, parent);
             DevicePolicyData policy = getUserDataUnchecked(credentialOwner);
             PasswordMetrics metrics = mLockSettingsInternal.getUserPasswordMetrics(credentialOwner);
-            return isActivePasswordSufficientForUserLocked(
+            boolean activePasswordSufficientForUserLocked = isActivePasswordSufficientForUserLocked(
                     policy.mPasswordValidAtLastCheckpoint, metrics, userHandle, parent);
+            return activePasswordSufficientForUserLocked;
         }
     }
 
@@ -4856,25 +4913,11 @@
      */
     private boolean isPasswordSufficientForUserWithoutCheckpointLocked(
             @NonNull PasswordMetrics metrics, @UserIdInt int userId, boolean parent) {
-        final int requiredQuality = getPasswordQuality(null, userId, parent);
-
-        if (requiredQuality >= PASSWORD_QUALITY_NUMERIC
-                && metrics.length < getPasswordMinimumLength(null, userId, parent)) {
-            return false;
-        }
-
-        // PASSWORD_QUALITY_COMPLEX doesn't represent actual password quality, it means that number
-        // of characters of each class should be checked instead of quality itself.
-        if (requiredQuality == PASSWORD_QUALITY_COMPLEX) {
-            return metrics.upperCase >= getPasswordMinimumUpperCase(null, userId, parent)
-                    && metrics.lowerCase >= getPasswordMinimumLowerCase(null, userId, parent)
-                    && metrics.letters >= getPasswordMinimumLetters(null, userId, parent)
-                    && metrics.numeric >= getPasswordMinimumNumeric(null, userId, parent)
-                    && metrics.symbols >= getPasswordMinimumSymbols(null, userId, parent)
-                    && metrics.nonLetter >= getPasswordMinimumNonLetter(null, userId, parent);
-        } else {
-            return metrics.quality >= requiredQuality;
-        }
+        PasswordMetrics minMetrics = getPasswordMinimumMetrics(userId, parent);
+        final List<PasswordValidationError> passwordValidationErrors =
+                PasswordMetrics.validatePasswordMetrics(
+                        minMetrics, PASSWORD_COMPLEXITY_NONE, false, metrics);
+        return passwordValidationErrors.isEmpty();
     }
 
     @Override
@@ -5132,77 +5175,17 @@
 
     private boolean resetPasswordInternal(String password, long tokenHandle, byte[] token,
             int flags, int callingUid, int userHandle) {
-        int quality;
         synchronized (getLockObject()) {
-            quality = getPasswordQuality(null, userHandle, /* parent */ false);
-            if (quality == PASSWORD_QUALITY_MANAGED) {
-                quality = PASSWORD_QUALITY_UNSPECIFIED;
-            }
             // TODO(b/120484642): remove getBytes() below
-            final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password.getBytes());
-            final int realQuality = metrics.quality;
-            if (realQuality < quality && quality != PASSWORD_QUALITY_COMPLEX) {
-                Slog.w(LOG_TAG, "resetPassword: password quality 0x"
-                        + Integer.toHexString(realQuality)
-                        + " does not meet required quality 0x"
-                        + Integer.toHexString(quality));
+            final PasswordMetrics minMetrics = getPasswordMinimumMetrics(userHandle);
+            final List<PasswordValidationError> validationErrors =
+                    PasswordMetrics.validatePassword(
+                            minMetrics, PASSWORD_COMPLEXITY_NONE, false, password.getBytes());
+            if (!validationErrors.isEmpty()) {
+                Log.w(LOG_TAG, "Failed to reset password due to constraint violation: "
+                        + validationErrors.get(0));
                 return false;
             }
-            quality = Math.max(realQuality, quality);
-            int length = getPasswordMinimumLength(null, userHandle, /* parent */ false);
-            if (password.length() < length) {
-                Slog.w(LOG_TAG, "resetPassword: password length " + password.length()
-                        + " does not meet required length " + length);
-                return false;
-            }
-            if (quality == PASSWORD_QUALITY_COMPLEX) {
-                int neededLetters = getPasswordMinimumLetters(null, userHandle, /* parent */ false);
-                if(metrics.letters < neededLetters) {
-                    Slog.w(LOG_TAG, "resetPassword: number of letters " + metrics.letters
-                            + " does not meet required number of letters " + neededLetters);
-                    return false;
-                }
-                int neededNumeric = getPasswordMinimumNumeric(null, userHandle, /* parent */ false);
-                if (metrics.numeric < neededNumeric) {
-                    Slog.w(LOG_TAG, "resetPassword: number of numerical digits " + metrics.numeric
-                            + " does not meet required number of numerical digits "
-                            + neededNumeric);
-                    return false;
-                }
-                int neededLowerCase = getPasswordMinimumLowerCase(
-                        null, userHandle, /* parent */ false);
-                if (metrics.lowerCase < neededLowerCase) {
-                    Slog.w(LOG_TAG, "resetPassword: number of lowercase letters "
-                            + metrics.lowerCase
-                            + " does not meet required number of lowercase letters "
-                            + neededLowerCase);
-                    return false;
-                }
-                int neededUpperCase = getPasswordMinimumUpperCase(
-                        null, userHandle, /* parent */ false);
-                if (metrics.upperCase < neededUpperCase) {
-                    Slog.w(LOG_TAG, "resetPassword: number of uppercase letters "
-                            + metrics.upperCase
-                            + " does not meet required number of uppercase letters "
-                            + neededUpperCase);
-                    return false;
-                }
-                int neededSymbols = getPasswordMinimumSymbols(null, userHandle, /* parent */ false);
-                if (metrics.symbols < neededSymbols) {
-                    Slog.w(LOG_TAG, "resetPassword: number of special symbols " + metrics.symbols
-                            + " does not meet required number of special symbols " + neededSymbols);
-                    return false;
-                }
-                int neededNonLetter = getPasswordMinimumNonLetter(
-                        null, userHandle, /* parent */ false);
-                if (metrics.nonLetter < neededNonLetter) {
-                    Slog.w(LOG_TAG, "resetPassword: number of non-letter characters "
-                            + metrics.nonLetter
-                            + " does not meet required number of non-letter characters "
-                            + neededNonLetter);
-                    return false;
-                }
-            }
         }
 
         DevicePolicyData policy = getUserData(userHandle);
@@ -5222,28 +5205,20 @@
         // back in to the service.
         final long ident = mInjector.binderClearCallingIdentity();
         final boolean result;
+        final LockscreenCredential newCredential =
+                LockscreenCredential.createPasswordOrNone(password);
         try {
             if (token == null) {
                 // This is the legacy reset password for DPM. Here we want to be able to override
                 // the old device password without necessarily knowing it.
-                if (!TextUtils.isEmpty(password)) {
-                    mLockPatternUtils.saveLockPassword(password.getBytes(), null, quality,
-                            userHandle, /*allowUntrustedChange */true);
-                } else {
-                    mLockPatternUtils.clearLock(null, userHandle,
-                            /*allowUntrustedChange */ true);
-                }
+                mLockPatternUtils.setLockCredential(
+                        newCredential,
+                        LockscreenCredential.createNone(),
+                        userHandle, /*allowUntrustedChange */true);
                 result = true;
             } else {
-                if (!TextUtils.isEmpty(password)) {
-                    result = mLockPatternUtils.setLockCredentialWithToken(password.getBytes(),
-                            LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                            quality, tokenHandle, token, userHandle);
-                } else {
-                    result = mLockPatternUtils.setLockCredentialWithToken(null,
-                            LockPatternUtils.CREDENTIAL_TYPE_NONE,
-                            quality, tokenHandle, token, userHandle);
-                }
+                result = mLockPatternUtils.setLockCredentialWithToken(newCredential, tokenHandle,
+                        token, userHandle);
             }
             boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
             if (requireEntry) {
@@ -11574,10 +11549,10 @@
 
     /**
      * Returns true if specified admin is allowed to limit passwords and has a
-     * {@code minimumPasswordMetrics.quality} of at least {@code minPasswordQuality}
+     * {@code mPasswordPolicy.quality} of at least {@code minPasswordQuality}
      */
     private static boolean isLimitPasswordAllowed(ActiveAdmin admin, int minPasswordQuality) {
-        if (admin.minimumPasswordMetrics.quality < minPasswordQuality) {
+        if (admin.mPasswordPolicy.quality < minPasswordQuality) {
             return false;
         }
         return admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
@@ -14196,13 +14171,13 @@
     }
 
     private void maybeLogPasswordComplexitySet(ComponentName who, int userId, boolean parent,
-            PasswordMetrics metrics) {
+            PasswordPolicy passwordPolicy) {
         if (SecurityLog.isLoggingEnabled()) {
             final int affectedUserId = parent ? getProfileParentId(userId) : userId;
             SecurityLog.writeEvent(SecurityLog.TAG_PASSWORD_COMPLEXITY_SET, who.getPackageName(),
-                    userId, affectedUserId, metrics.length, metrics.quality, metrics.letters,
-                    metrics.nonLetter, metrics.numeric, metrics.upperCase, metrics.lowerCase,
-                    metrics.symbols);
+                    userId, affectedUserId, passwordPolicy.length, passwordPolicy.quality,
+                    passwordPolicy.letters, passwordPolicy.nonLetter, passwordPolicy.numeric,
+                    passwordPolicy.upperCase, passwordPolicy.lowerCase, passwordPolicy.symbols);
         }
     }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
index 0838fbc..7cfbcc8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
@@ -51,7 +51,7 @@
     static final long REMOTE_BUGREPORT_TIMEOUT_MILLIS = 10 * DateUtils.MINUTE_IN_MILLIS;
 
     static final String CTL_STOP = "ctl.stop";
-    static final String REMOTE_BUGREPORT_SERVICE = "bugreportremote";
+    static final String REMOTE_BUGREPORT_SERVICE = "bugreportd";
 
     static final String BUGREPORT_MIMETYPE = "application/vnd.android.bugreport";
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 4cf98d3..88859a7 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -921,7 +921,6 @@
                 false);
         boolean disableCameraService = SystemProperties.getBoolean("config.disable_cameraservice",
                 false);
-        boolean disableSlices = SystemProperties.getBoolean("config.disable_slices", false);
         boolean enableLeftyService = SystemProperties.getBoolean("config.enable_lefty", false);
 
         boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1");
@@ -1856,7 +1855,7 @@
             t.traceEnd();
         }
 
-        if (!disableSlices) {
+        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_SLICES_DISABLED)) {
             t.traceBegin("StartSliceManagerService");
             mSystemServiceManager.startService(SLICE_MANAGER_SERVICE_CLASS);
             t.traceEnd();
diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java
index 6a6a130..3d79bba 100644
--- a/services/net/java/android/net/ip/IpServer.java
+++ b/services/net/java/android/net/ip/IpServer.java
@@ -93,6 +93,8 @@
     private static final int USB_PREFIX_LENGTH = 24;
     private static final String WIFI_HOST_IFACE_ADDR = "192.168.43.1";
     private static final int WIFI_HOST_IFACE_PREFIX_LENGTH = 24;
+    private static final String WIFI_P2P_IFACE_ADDR = "192.168.49.1";
+    private static final int WIFI_P2P_IFACE_PREFIX_LENGTH = 24;
 
     // TODO: have PanService use some visible version of this constant
     private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1";
@@ -403,6 +405,9 @@
         } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
             ipAsString = getRandomWifiIPv4Address();
             prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
+        } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI_P2P) {
+            ipAsString = WIFI_P2P_IFACE_ADDR;
+            prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH;
         } else {
             // BT configures the interface elsewhere: only start DHCP.
             final Inet4Address srvAddr = (Inet4Address) numericToInetAddress(BLUETOOTH_IFACE_ADDR);
diff --git a/services/print/java/com/android/server/print/TEST_MAPPING b/services/print/java/com/android/server/print/TEST_MAPPING
new file mode 100644
index 0000000..4fa8822
--- /dev/null
+++ b/services/print/java/com/android/server/print/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsPrintTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        }
+      ]
+    }
+  ]
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
index 6e8b86a..7b7b8e6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -34,7 +34,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 import static com.android.server.AlarmManagerService.ACTIVE_INDEX;
 import static com.android.server.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED;
-import static com.android.server.AlarmManagerService.AlarmHandler.APP_STANDBY_PAROLE_CHANGED;
+import static com.android.server.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED;
 import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_LONG_TIME;
 import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME;
 import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
@@ -53,6 +53,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.atLeastOnce;
@@ -68,6 +69,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -107,6 +109,7 @@
     private long mAppStandbyWindow;
     private AlarmManagerService mService;
     private UsageStatsManagerInternal.AppIdleStateChangeListener mAppStandbyListener;
+    private AlarmManagerService.ChargingReceiver mChargingReceiver;
     @Mock
     private ContentResolver mMockResolver;
     @Mock
@@ -290,6 +293,13 @@
                 ArgumentCaptor.forClass(UsageStatsManagerInternal.AppIdleStateChangeListener.class);
         verify(mUsageStatsManagerInternal).addAppIdleStateChangeListener(captor.capture());
         mAppStandbyListener = captor.getValue();
+
+        ArgumentCaptor<AlarmManagerService.ChargingReceiver> chargingReceiverCaptor =
+                ArgumentCaptor.forClass(AlarmManagerService.ChargingReceiver.class);
+        verify(mMockContext).registerReceiver(chargingReceiverCaptor.capture(),
+                argThat((filter) -> filter.hasAction(BatteryManager.ACTION_CHARGING)
+                        && filter.hasAction(BatteryManager.ACTION_DISCHARGING)));
+        mChargingReceiver = chargingReceiverCaptor.getValue();
     }
 
     private void setTestAlarm(int type, long triggerTime, PendingIntent operation) {
@@ -724,17 +734,19 @@
     }
 
     private void assertAndHandleParoleChanged(boolean parole) {
-        mAppStandbyListener.onParoleStateChanged(parole);
+        mChargingReceiver.onReceive(mMockContext,
+                new Intent(parole ? BatteryManager.ACTION_CHARGING
+                        : BatteryManager.ACTION_DISCHARGING));
         final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
         verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture());
         final Message lastMessage = messageCaptor.getValue();
         assertEquals("Unexpected message send to handler", lastMessage.what,
-                APP_STANDBY_PAROLE_CHANGED);
+                CHARGING_STATUS_CHANGED);
         mService.mHandler.handleMessage(lastMessage);
     }
 
     @Test
-    public void testParole() throws Exception {
+    public void testCharging() throws Exception {
         setQuotasEnabled(true);
         final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET);
         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
diff --git a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
index d0158e0..80d1129 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
@@ -64,6 +64,9 @@
 import android.util.ArraySet;
 import android.util.Pair;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.app.IAppOpsService;
 import com.android.server.AppStateTracker.Listener;
@@ -85,14 +88,10 @@
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
 /**
  * Tests for {@link AppStateTracker}
  *
- * Run with:
- atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
+ * Run with: atest com.android.server.AppStateTrackerTest
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -685,10 +684,12 @@
         List<OpEntry> entries = new ArrayList<>();
         entries.add(new OpEntry(
                 AppOpsManager.OP_ACCESS_NOTIFICATIONS,
-                AppOpsManager.MODE_IGNORED));
+                AppOpsManager.MODE_IGNORED,
+                new Pair[0]));
         entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
-                AppOpsManager.MODE_IGNORED));
+                AppOpsManager.MODE_IGNORED,
+                new Pair[0]));
 
         ops.add(new PackageOps(PACKAGE_1, UID_1, entries));
 
@@ -696,7 +697,8 @@
         entries = new ArrayList<>();
         entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
-                AppOpsManager.MODE_IGNORED));
+                AppOpsManager.MODE_IGNORED,
+                new Pair[0]));
 
         ops.add(new PackageOps(PACKAGE_2, UID_2, entries));
 
@@ -704,7 +706,8 @@
         entries = new ArrayList<>();
         entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
-                AppOpsManager.MODE_ALLOWED));
+                AppOpsManager.MODE_ALLOWED,
+                new Pair[0]));
 
         ops.add(new PackageOps(PACKAGE_1, UID_10_1, entries));
 
@@ -712,10 +715,12 @@
         entries = new ArrayList<>();
         entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
-                AppOpsManager.MODE_IGNORED));
+                AppOpsManager.MODE_IGNORED,
+                new Pair[0]));
         entries.add(new OpEntry(
                 AppOpsManager.OP_ACCESS_NOTIFICATIONS,
-                AppOpsManager.MODE_IGNORED));
+                AppOpsManager.MODE_IGNORED,
+                new Pair[0]));
 
         ops.add(new PackageOps(PACKAGE_3, UID_10_3, entries));
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 8b3c85e..6dd1bd8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -141,8 +141,10 @@
 
         sService.mConstants = new ActivityManagerConstants(sContext, sService,
                 sContext.getMainThreadHandler());
+        ProcessList pr = new ProcessList();
+        pr.init(sService, new ActiveUids(sService, false));
         setFieldValue(ActivityManagerService.class, sService, "mProcessList",
-                new ProcessList());
+                pr);
         setFieldValue(ActivityManagerService.class, sService, "mHandler",
                 mock(ActivityManagerService.MainHandler.class));
         setFieldValue(ActivityManagerService.class, sService, "mProcessStats",
@@ -346,11 +348,13 @@
     public void testUpdateOomAdj_DoOne_RecentTasks() {
         ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
-        doReturn(true).when(app).hasRecentTasks();
+        doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
+        WindowProcessController wpc = app.getWindowProcessController();
+        doReturn(true).when(wpc).hasRecentTasks();
         app.lastTopTime = SystemClock.uptimeMillis();
         sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
         sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
-        doCallRealMethod().when(app).hasRecentTasks();
+        doCallRealMethod().when(wpc).hasRecentTasks();
 
         assertEquals(PROCESS_STATE_CACHED_RECENT, app.setProcState);
     }
@@ -459,7 +463,7 @@
         doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
         WindowProcessController wpc = app.getWindowProcessController();
         doReturn(true).when(wpc).isPreviousProcess();
-        doReturn(true).when(app).hasActivities();
+        doReturn(true).when(wpc).hasActivities();
         sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
         sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
 
@@ -644,7 +648,7 @@
         WindowProcessController wpc = app.getWindowProcessController();
         doReturn(false).when(wpc).isHomeProcess();
         doReturn(true).when(wpc).isPreviousProcess();
-        doReturn(true).when(app).hasActivities();
+        doReturn(true).when(wpc).hasActivities();
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
         bindService(app, client, null, Context.BIND_ALLOW_OOM_MANAGEMENT, mock(IBinder.class));
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 06366cf..b6a7b09 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -162,12 +162,12 @@
         mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
 
         // Note an op that's allowed.
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
         List<PackageOps> loggedOps = getLoggedOps();
         assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
 
         // Note another op that's not allowed.
-        mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null);
         loggedOps = getLoggedOps();
         assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
         assertContainsOp(loggedOps, OP_WRITE_SMS, -1, mTestStartMillis, MODE_ERRORED);
@@ -183,7 +183,7 @@
         // This op controls WIFI_SCAN
         mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ALLOWED);
 
-        assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ALLOWED);
 
         assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, -1,
@@ -191,7 +191,7 @@
 
         // Now set COARSE_LOCATION to ERRORED -> this will make WIFI_SCAN disabled as well.
         mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ERRORED);
-        assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ERRORED);
 
         assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, mTestStartMillis,
@@ -203,8 +203,8 @@
     public void testStatePersistence() {
         mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
         mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
-        mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
+        mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null);
         mAppOpsService.writeState();
 
         // Create a new app ops service, and initialize its state from XML.
@@ -221,7 +221,7 @@
     @Test
     public void testShutdown() {
         mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
         mAppOpsService.shutdown();
 
         // Create a new app ops service, and initialize its state from XML.
@@ -236,7 +236,7 @@
     @Test
     public void testGetOpsForPackage() {
         mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
 
         // Query all ops
         List<PackageOps> loggedOps = mAppOpsService.getOpsForPackage(
@@ -265,7 +265,7 @@
     @Test
     public void testPackageRemoved() {
         mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
 
         List<PackageOps> loggedOps = getLoggedOps();
         assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
@@ -278,7 +278,7 @@
     @Test
     public void testPackageRemovedHistoricalOps() throws InterruptedException {
         mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
 
         AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000);
         historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, sMyPackageName,
@@ -317,7 +317,7 @@
     @Test
     public void testUidRemoved() {
         mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
 
         List<PackageOps> loggedOps = getLoggedOps();
         assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
@@ -339,18 +339,18 @@
         setupProcStateTests();
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
         // Second time to make sure that settle time is overcome
         Thread.sleep(50);
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
     }
 
@@ -359,11 +359,11 @@
         setupProcStateTests();
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
     }
 
@@ -372,12 +372,12 @@
         setupProcStateTests();
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid,
                 PROCESS_STATE_FOREGROUND_SERVICE_LOCATION);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ALLOWED);
     }
 
@@ -386,18 +386,18 @@
         setupProcStateTests();
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
         // Second time to make sure that settle time is overcome
         Thread.sleep(50);
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
     }
 
@@ -406,25 +406,25 @@
         setupProcStateTests();
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE_LOCATION);
         // Second time to make sure that settle time is overcome
         Thread.sleep(50);
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE_LOCATION);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
         // Second time to make sure that settle time is overcome
         Thread.sleep(50);
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
index edf82ee..597d337 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
@@ -41,12 +41,14 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.testing.DexmakerShareClassLoaderRule;
 import android.view.Display;
 
 import com.android.server.wm.WindowManagerInternal;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
@@ -65,9 +67,14 @@
             "com.android.server.accessibility", "AccessibilityServiceConnectionTest");
     static final int SERVICE_ID = 42;
 
+    // Mock package-private AccessibilityUserState class
+    @Rule
+    public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
+            new DexmakerShareClassLoaderRule();
+
     AccessibilityServiceConnection mConnection;
 
-    @Mock AccessibilityManagerService.UserState mMockUserState;
+    @Mock AccessibilityUserState mMockUserState;
     @Mock Context mMockContext;
     @Mock AccessibilityServiceInfo mMockServiceInfo;
     @Mock ResolveInfo mMockResolveInfo;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
new file mode 100644
index 0000000..d70e164
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
@@ -0,0 +1,297 @@
+/*
+ * 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.server.accessibility;
+
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_AUTO;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN;
+import static android.accessibilityservice.AccessibilityService.SHOW_MODE_IGNORE_HARD_KEYBOARD;
+import static android.view.accessibility.AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
+import static android.view.accessibility.AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
+import static android.view.accessibility.AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.provider.Settings;
+import android.test.mock.MockContentResolver;
+import android.testing.DexmakerShareClassLoaderRule;
+
+import com.android.internal.util.test.FakeSettingsProvider;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Tests for AccessibilityUserState */
+public class AccessibilityUserStateTest {
+
+    private static final ComponentName COMPONENT_NAME =
+            new ComponentName("com.android.server.accessibility", "AccessibilityUserStateTest");
+
+    // Values of setting key SHOW_IME_WITH_HARD_KEYBOARD
+    private static final int STATE_HIDE_IME = 0;
+    private static final int STATE_SHOW_IME = 1;
+
+    private static final int USER_ID = 42;
+
+    // Mock package-private class AccessibilityServiceConnection
+    @Rule public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
+            new DexmakerShareClassLoaderRule();
+
+    @Mock private AccessibilityServiceInfo mMockServiceInfo;
+
+    @Mock private AccessibilityServiceConnection mMockConnection;
+
+    @Mock private AccessibilityUserState.ServiceInfoChangeListener mMockListener;
+
+    @Mock private Context mContext;
+
+    private MockContentResolver mMockResolver;
+
+    private AccessibilityUserState mUserState;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        FakeSettingsProvider.clearSettingsProvider();
+        mMockResolver = new MockContentResolver();
+        mMockResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+        when(mContext.getContentResolver()).thenReturn(mMockResolver);
+        when(mMockServiceInfo.getComponentName()).thenReturn(COMPONENT_NAME);
+        when(mMockConnection.getServiceInfo()).thenReturn(mMockServiceInfo);
+
+        mUserState = new AccessibilityUserState(USER_ID, mContext, mMockListener);
+    }
+
+    @After
+    public void tearDown() {
+        FakeSettingsProvider.clearSettingsProvider();
+    }
+
+    @Test
+    public void onSwitchToAnotherUser_userStateClearedNonDefaultValues() {
+        mUserState.getBoundServicesLocked().add(mMockConnection);
+        mUserState.getBindingServicesLocked().add(COMPONENT_NAME);
+        mUserState.setLastSentClientStateLocked(
+                STATE_FLAG_ACCESSIBILITY_ENABLED
+                        | STATE_FLAG_TOUCH_EXPLORATION_ENABLED
+                        | STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED);
+        mUserState.setNonInteractiveUiTimeoutLocked(30);
+        mUserState.setInteractiveUiTimeoutLocked(30);
+        mUserState.mEnabledServices.add(COMPONENT_NAME);
+        mUserState.mTouchExplorationGrantedServices.add(COMPONENT_NAME);
+        mUserState.setTouchExplorationEnabledLocked(true);
+        mUserState.setDisplayMagnificationEnabledLocked(true);
+        mUserState.setNavBarMagnificationEnabledLocked(true);
+        mUserState.setServiceAssignedToAccessibilityButtonLocked(COMPONENT_NAME);
+        mUserState.setNavBarMagnificationAssignedToAccessibilityButtonLocked(true);
+        mUserState.setAutoclickEnabledLocked(true);
+        mUserState.setUserNonInteractiveUiTimeoutLocked(30);
+        mUserState.setUserInteractiveUiTimeoutLocked(30);
+
+        mUserState.onSwitchToAnotherUserLocked();
+
+        verify(mMockConnection).unbindLocked();
+        assertTrue(mUserState.getBoundServicesLocked().isEmpty());
+        assertTrue(mUserState.getBindingServicesLocked().isEmpty());
+        assertEquals(-1, mUserState.getLastSentClientStateLocked());
+        assertEquals(0, mUserState.getNonInteractiveUiTimeoutLocked());
+        assertEquals(0, mUserState.getInteractiveUiTimeoutLocked());
+        assertTrue(mUserState.mEnabledServices.isEmpty());
+        assertTrue(mUserState.mTouchExplorationGrantedServices.isEmpty());
+        assertFalse(mUserState.isTouchExplorationEnabledLocked());
+        assertFalse(mUserState.isDisplayMagnificationEnabledLocked());
+        assertFalse(mUserState.isNavBarMagnificationEnabledLocked());
+        assertNull(mUserState.getServiceAssignedToAccessibilityButtonLocked());
+        assertFalse(mUserState.isNavBarMagnificationAssignedToAccessibilityButtonLocked());
+        assertFalse(mUserState.isAutoclickEnabledLocked());
+        assertEquals(0, mUserState.getUserNonInteractiveUiTimeoutLocked());
+        assertEquals(0, mUserState.getUserInteractiveUiTimeoutLocked());
+    }
+
+    @Test
+    public void addService_connectionAlreadyAdded_notAddAgain() {
+        mUserState.getBoundServicesLocked().add(mMockConnection);
+
+        mUserState.addServiceLocked(mMockConnection);
+
+        verify(mMockConnection, never()).onAdded();
+    }
+
+    @Test
+    public void addService_connectionNotYetAddedToBoundService_addAndNotifyServices() {
+        when(mMockConnection.getComponentName()).thenReturn(COMPONENT_NAME);
+
+        mUserState.addServiceLocked(mMockConnection);
+
+        verify(mMockConnection).onAdded();
+        assertTrue(mUserState.getBoundServicesLocked().contains(mMockConnection));
+        assertEquals(mMockConnection, mUserState.mComponentNameToServiceMap.get(COMPONENT_NAME));
+        verify(mMockListener).onServiceInfoChangedLocked(eq(mUserState));
+    }
+
+    @Test
+    public void reconcileSoftKeyboardMode_whenStateNotMatchSettings_setBothDefault() {
+        // When soft kb show mode is hidden in settings and is auto in state.
+        putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                SHOW_MODE_HIDDEN, USER_ID);
+
+        mUserState.reconcileSoftKeyboardModeWithSettingsLocked();
+
+        assertEquals(SHOW_MODE_AUTO, mUserState.getSoftKeyboardShowModeLocked());
+        assertEquals(SHOW_MODE_AUTO, getSecureIntForUser(
+                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, USER_ID));
+        assertNull(mUserState.getServiceChangingSoftKeyboardModeLocked());
+    }
+
+    @Test
+    public void
+            reconcileSoftKeyboardMode_stateIgnoreHardKb_settingsShowImeHardKb_setAutoOverride() {
+        // When show mode is ignore hard kb without original hard kb value
+        // and show ime with hard kb is hide
+        putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                SHOW_MODE_IGNORE_HARD_KEYBOARD, USER_ID);
+        mUserState.setSoftKeyboardModeLocked(SHOW_MODE_IGNORE_HARD_KEYBOARD, COMPONENT_NAME);
+        putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
+                STATE_HIDE_IME, USER_ID);
+
+        mUserState.reconcileSoftKeyboardModeWithSettingsLocked();
+
+        assertEquals(SHOW_MODE_AUTO | SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN,
+                getSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, USER_ID));
+        assertNull(mUserState.getServiceChangingSoftKeyboardModeLocked());
+    }
+
+    @Test
+    public void removeService_serviceChangingSoftKeyboardMode_removeAndSetSoftKbModeAuto() {
+        mUserState.setServiceChangingSoftKeyboardModeLocked(COMPONENT_NAME);
+        mUserState.mComponentNameToServiceMap.put(COMPONENT_NAME, mMockConnection);
+        mUserState.setSoftKeyboardModeLocked(SHOW_MODE_HIDDEN, COMPONENT_NAME);
+
+        mUserState.removeServiceLocked(mMockConnection);
+
+        assertFalse(mUserState.getBoundServicesLocked().contains(mMockConnection));
+        verify(mMockConnection).onRemoved();
+        assertEquals(SHOW_MODE_AUTO, mUserState.getSoftKeyboardShowModeLocked());
+        assertNull(mUserState.mComponentNameToServiceMap.get(COMPONENT_NAME));
+        verify(mMockListener).onServiceInfoChangedLocked(eq(mUserState));
+    }
+
+    @Test
+    public void serviceDisconnected_removeServiceAndAddToCrashed() {
+        when(mMockConnection.getComponentName()).thenReturn(COMPONENT_NAME);
+        mUserState.addServiceLocked(mMockConnection);
+
+        mUserState.serviceDisconnectedLocked(mMockConnection);
+
+        assertFalse(mUserState.getBoundServicesLocked().contains(mMockConnection));
+        assertTrue(mUserState.getCrashedServicesLocked().contains(COMPONENT_NAME));
+    }
+
+    @Test
+    public void setSoftKeyboardMode_withInvalidShowMode_shouldKeepDefaultAuto() {
+        final int invalidShowMode = SHOW_MODE_HIDDEN | SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE;
+
+        assertFalse(mUserState.setSoftKeyboardModeLocked(invalidShowMode, null));
+
+        assertEquals(SHOW_MODE_AUTO, mUserState.getSoftKeyboardShowModeLocked());
+    }
+
+    @Test
+    public void setSoftKeyboardMode_newModeSameWithCurrentState_returnTrue() {
+        when(mMockConnection.getComponentName()).thenReturn(COMPONENT_NAME);
+        mUserState.addServiceLocked(mMockConnection);
+
+        assertTrue(mUserState.setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null));
+    }
+
+    @Test
+    public void setSoftKeyboardMode_withIgnoreHardKb_whenHardKbOverridden_returnFalseAdNoChange() {
+        putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                SHOW_MODE_AUTO | SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN, USER_ID);
+
+        assertFalse(mUserState.setSoftKeyboardModeLocked(SHOW_MODE_IGNORE_HARD_KEYBOARD, null));
+
+        assertEquals(SHOW_MODE_AUTO, mUserState.getSoftKeyboardShowModeLocked());
+    }
+
+    @Test
+    public void
+            setSoftKeyboardMode_withIgnoreHardKb_whenShowImeWithHardKb_setOriginalHardKbValue() {
+        putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, STATE_SHOW_IME, USER_ID);
+
+        assertTrue(mUserState.setSoftKeyboardModeLocked(SHOW_MODE_IGNORE_HARD_KEYBOARD, null));
+
+        assertEquals(SHOW_MODE_IGNORE_HARD_KEYBOARD | SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE,
+                getSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, USER_ID));
+    }
+
+    @Test
+    public void setSoftKeyboardMode_whenCurrentIgnoreHardKb_shouldSetShowImeWithHardKbValue() {
+        mUserState.setSoftKeyboardModeLocked(SHOW_MODE_IGNORE_HARD_KEYBOARD, COMPONENT_NAME);
+        putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, STATE_HIDE_IME, USER_ID);
+        putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                SHOW_MODE_IGNORE_HARD_KEYBOARD | SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE, USER_ID);
+
+        assertTrue(mUserState.setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null));
+
+        assertEquals(STATE_SHOW_IME, getSecureIntForUser(
+                Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, USER_ID));
+    }
+
+    @Test
+    public void setSoftKeyboardMode_withRequester_shouldUpdateInternalStateAndSettingsAsIs() {
+        assertTrue(mUserState.setSoftKeyboardModeLocked(SHOW_MODE_HIDDEN, COMPONENT_NAME));
+
+        assertEquals(SHOW_MODE_HIDDEN, mUserState.getSoftKeyboardShowModeLocked());
+        assertEquals(SHOW_MODE_HIDDEN, getSecureIntForUser(
+                Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, USER_ID));
+        assertEquals(COMPONENT_NAME, mUserState.getServiceChangingSoftKeyboardModeLocked());
+    }
+
+    @Test
+    public void setSoftKeyboardMode_shouldNotifyBoundService() {
+        mUserState.addServiceLocked(mMockConnection);
+
+        assertTrue(mUserState.setSoftKeyboardModeLocked(SHOW_MODE_HIDDEN, COMPONENT_NAME));
+
+        verify(mMockConnection).notifySoftKeyboardShowModeChangedLocked(eq(SHOW_MODE_HIDDEN));
+    }
+
+    private int getSecureIntForUser(String key, int userId) {
+        return Settings.Secure.getIntForUser(mMockResolver, key, -1, userId);
+    }
+
+    private void putSecureIntForUser(String key, int value, int userId) {
+        Settings.Secure.putIntForUser(mMockResolver, key, value, userId);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
index deb6f71..8da927d 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java
@@ -56,7 +56,6 @@
 
     MessageCapturingHandler mMessageCapturingHandler;
 
-    @Mock AccessibilityManagerService.UserState mMockUserState;
     @Mock Context mMockContext;
     @Mock AccessibilityServiceInfo mMockServiceInfo;
     @Mock ResolveInfo mMockResolveInfo;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 29244f0..1edc953 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -34,9 +34,9 @@
 import static com.android.server.am.ActivityManagerInternalTest.CustomThread;
 import static com.android.server.am.ActivityManagerService.DISPATCH_UIDS_CHANGED_UI_MSG;
 import static com.android.server.am.ActivityManagerService.Injector;
-import static com.android.server.am.ActivityManagerService.NETWORK_STATE_BLOCK;
-import static com.android.server.am.ActivityManagerService.NETWORK_STATE_NO_CHANGE;
-import static com.android.server.am.ActivityManagerService.NETWORK_STATE_UNBLOCK;
+import static com.android.server.am.ProcessList.NETWORK_STATE_BLOCK;
+import static com.android.server.am.ProcessList.NETWORK_STATE_NO_CHANGE;
+import static com.android.server.am.ProcessList.NETWORK_STATE_UNBLOCK;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -274,7 +274,7 @@
 
         uidRec.setProcState = prevState;
         uidRec.setCurProcState(curState);
-        mAms.incrementProcStateSeqAndNotifyAppsLocked();
+        mAms.mProcessList.incrementProcStateSeqAndNotifyAppsLocked(mAms.mProcessList.mActiveUids);
 
         // @SuppressWarnings("GuardedBy")
         assertEquals(expectedGlobalCounter, mAms.mProcessList.mProcStateSeqCounter);
@@ -429,42 +429,42 @@
         uidRec.setCurProcState(PROCESS_STATE_RECEIVER);
         expectedBlockState = NETWORK_STATE_NO_CHANGE;
         assertEquals(errorMsg.apply(expectedBlockState),
-                expectedBlockState, mAms.getBlockStateForUid(uidRec));
+                expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
 
         // Foreground to foreground
         uidRec.setProcState = PROCESS_STATE_FOREGROUND_SERVICE;
         uidRec.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
         expectedBlockState = NETWORK_STATE_NO_CHANGE;
         assertEquals(errorMsg.apply(expectedBlockState),
-                expectedBlockState, mAms.getBlockStateForUid(uidRec));
+                expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
 
         // Background to background
         uidRec.setProcState = PROCESS_STATE_CACHED_ACTIVITY;
         uidRec.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
         expectedBlockState = NETWORK_STATE_NO_CHANGE;
         assertEquals(errorMsg.apply(expectedBlockState),
-                expectedBlockState, mAms.getBlockStateForUid(uidRec));
+                expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
 
         // Background to background
         uidRec.setProcState = PROCESS_STATE_NONEXISTENT;
         uidRec.setCurProcState(PROCESS_STATE_CACHED_ACTIVITY);
         expectedBlockState = NETWORK_STATE_NO_CHANGE;
         assertEquals(errorMsg.apply(expectedBlockState),
-                expectedBlockState, mAms.getBlockStateForUid(uidRec));
+                expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
 
         // Background to foreground
         uidRec.setProcState = PROCESS_STATE_SERVICE;
         uidRec.setCurProcState(PROCESS_STATE_FOREGROUND_SERVICE);
         expectedBlockState = NETWORK_STATE_BLOCK;
         assertEquals(errorMsg.apply(expectedBlockState),
-                expectedBlockState, mAms.getBlockStateForUid(uidRec));
+                expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
 
         // Foreground to background
         uidRec.setProcState = PROCESS_STATE_TOP;
         uidRec.setCurProcState(PROCESS_STATE_LAST_ACTIVITY);
         expectedBlockState = NETWORK_STATE_UNBLOCK;
         assertEquals(errorMsg.apply(expectedBlockState),
-                expectedBlockState, mAms.getBlockStateForUid(uidRec));
+                expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
     }
 
     /**
@@ -473,8 +473,8 @@
      */
     @Test
     public void testDispatchUids_dispatchNeededChanges() throws RemoteException {
-        when(mAppOpsService.noteOperation(AppOpsManager.OP_GET_USAGE_STATS, Process.myUid(), null))
-                .thenReturn(AppOpsManager.MODE_ALLOWED);
+        when(mAppOpsService.noteOperation(AppOpsManager.OP_GET_USAGE_STATS, Process.myUid(), null,
+                null)).thenReturn(AppOpsManager.MODE_ALLOWED);
 
         final int[] changesToObserve = {
             ActivityManager.UID_OBSERVER_PROCSTATE,
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 9a1fd9c..aeccfc5 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -25,10 +25,12 @@
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
 import static android.app.admin.DevicePolicyManager.WIPE_EUICC;
+import static android.app.admin.PasswordMetrics.computeForPassword;
 import static android.os.UserManagerInternal.CAMERA_DISABLED_GLOBALLY;
 import static android.os.UserManagerInternal.CAMERA_DISABLED_LOCALLY;
 import static android.os.UserManagerInternal.CAMERA_NOT_DISABLED;
 
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
 import static com.android.server.testutils.TestUtils.assertExpectException;
 
@@ -93,7 +95,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.R;
-import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockscreenCredential;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.devicepolicy.DevicePolicyManagerService.RestrictionsListener;
@@ -4266,9 +4268,9 @@
         assertTrue(dpm.isResetPasswordTokenActive(admin1));
 
         // test reset password with token
-        when(getServices().lockPatternUtils.setLockCredentialWithToken(eq(password.getBytes()),
-                eq(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD),
-                eq(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC), eq(handle), eq(token),
+        when(getServices().lockPatternUtils.setLockCredentialWithToken(
+                eq(LockscreenCredential.createPassword(password)),
+                eq(handle), eq(token),
                 eq(UserHandle.USER_SYSTEM)))
                 .thenReturn(true);
         assertTrue(dpm.resetPasswordWithToken(admin1, password, token, 0));
@@ -4295,11 +4297,7 @@
 
         reset(mContext.spiedContext);
 
-        PasswordMetrics passwordMetricsNoSymbols = new PasswordMetrics(
-                DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, 9,
-                8, 2,
-                6, 1,
-                0, 1);
+        PasswordMetrics passwordMetricsNoSymbols = computeForPassword("abcdXYZ5".getBytes());
 
         setActivePasswordState(passwordMetricsNoSymbols);
         assertTrue(dpm.isActivePasswordSufficient());
@@ -4326,11 +4324,7 @@
         reset(mContext.spiedContext);
         assertFalse(dpm.isActivePasswordSufficient());
 
-        PasswordMetrics passwordMetricsWithSymbols = new PasswordMetrics(
-                DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, 9,
-                7, 2,
-                5, 1,
-                1, 2);
+        PasswordMetrics passwordMetricsWithSymbols = computeForPassword("abcd.XY5".getBytes());
 
         setActivePasswordState(passwordMetricsWithSymbols);
         assertTrue(dpm.isActivePasswordSufficient());
@@ -4347,7 +4341,7 @@
         final int userHandle = UserHandle.getUserId(mContext.binder.callingUid);
         // When there is no lockscreen, user password metrics is always empty.
         when(getServices().lockSettingsInternal.getUserPasswordMetrics(userHandle))
-                .thenReturn(new PasswordMetrics());
+                .thenReturn(new PasswordMetrics(CREDENTIAL_TYPE_NONE));
 
         // If no password requirements are set, isActivePasswordSufficient should succeed.
         assertTrue(dpm.isActivePasswordSufficient());
@@ -5314,7 +5308,7 @@
                 .thenReturn(DpmMockContext.CALLER_USER_HANDLE);
         when(getServices().lockSettingsInternal
                 .getUserPasswordMetrics(DpmMockContext.CALLER_USER_HANDLE))
-                .thenReturn(PasswordMetrics.computeForPassword("asdf".getBytes()));
+                .thenReturn(computeForPassword("asdf".getBytes()));
 
         assertEquals(PASSWORD_COMPLEXITY_MEDIUM, dpm.getPasswordComplexity());
     }
@@ -5331,10 +5325,10 @@
 
         when(getServices().lockSettingsInternal
                 .getUserPasswordMetrics(DpmMockContext.CALLER_USER_HANDLE))
-                .thenReturn(PasswordMetrics.computeForPassword("asdf".getBytes()));
+                .thenReturn(computeForPassword("asdf".getBytes()));
         when(getServices().lockSettingsInternal
                 .getUserPasswordMetrics(parentUser.id))
-                .thenReturn(PasswordMetrics.computeForPassword("parentUser".getBytes()));
+                .thenReturn(computeForPassword("parentUser".getBytes()));
 
         assertEquals(PASSWORD_COMPLEXITY_HIGH, dpm.getPasswordComplexity());
     }
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 f9ac022..537287d 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -35,7 +35,9 @@
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.hardware.authsecret.V1_0.IAuthSecret;
+import android.hardware.face.Face;
 import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.FileUtils;
 import android.os.IProgressListener;
@@ -249,11 +251,32 @@
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)).thenReturn(true);
         when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
         when(mFingerprintManager.hasEnrolledFingerprints(userId)).thenReturn(true);
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                Fingerprint fp = (Fingerprint) invocation.getArguments()[0];
+                FingerprintManager.RemovalCallback callback =
+                        (FingerprintManager.RemovalCallback) invocation.getArguments()[2];
+                callback.onRemovalSucceeded(fp, 0);
+                return null;
+            }
+        }).when(mFingerprintManager).remove(any(), eq(userId), any());
+
 
         // Hardware must be detected and templates must be enrolled
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
         when(mFaceManager.isHardwareDetected()).thenReturn(true);
         when(mFaceManager.hasEnrolledTemplates(userId)).thenReturn(true);
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                Face face = (Face) invocation.getArguments()[0];
+                FaceManager.RemovalCallback callback =
+                        (FaceManager.RemovalCallback) invocation.getArguments()[2];
+                callback.onRemovalSucceeded(face, 0);
+                return null;
+            }
+        }).when(mFaceManager).remove(any(), eq(userId), any());
     }
 
     @Override
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
index c00d33b..b60111e 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
@@ -19,10 +19,9 @@
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
 
-import static com.android.internal.widget.LockPatternUtils.stringToPattern;
-
 import static junit.framework.Assert.assertEquals;
 
+import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.never;
@@ -48,6 +47,8 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+import com.android.internal.widget.LockscreenCredential;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -55,6 +56,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.List;
+
 /**
  * Test class for {@link LockSettingsShellCommand}.
  *
@@ -87,24 +90,30 @@
     public void testWrongPassword() throws Exception {
         when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
         when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
-        when(mLockPatternUtils.checkPassword("1234".getBytes(), mUserId)).thenReturn(false);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPassword("1234"), mUserId, null)).thenReturn(false);
         assertEquals(-1, mCommand.exec(mBinder, in, out, err,
                 new String[] { "set-pin", "--old", "1234" },
                 mShellCallback, mResultReceiver));
-        verify(mLockPatternUtils, never()).saveLockPassword(any(byte[].class), any(byte[].class),
-                anyInt(), anyInt());
+        verify(mLockPatternUtils, never()).setLockCredential(any(), any(),
+                anyInt(), anyBoolean());
     }
 
     @Test
     public void testChangePin() throws Exception {
         when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
         when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
-        when(mLockPatternUtils.checkPassword("1234".getBytes(), mUserId)).thenReturn(true);
+        when(mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)).thenReturn(
+                PASSWORD_QUALITY_NUMERIC);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPin("1234"), mUserId, null)).thenReturn(true);
         assertEquals(0, mCommand.exec(new Binder(), in, out, err,
                 new String[] { "set-pin", "--old", "1234", "4321" },
                 mShellCallback, mResultReceiver));
-        verify(mLockPatternUtils).saveLockPassword("4321".getBytes(), "1234".getBytes(),
-                PASSWORD_QUALITY_NUMERIC, mUserId);
+        verify(mLockPatternUtils).setLockCredential(
+                LockscreenCredential.createPin("4321"),
+                LockscreenCredential.createPin("1234"),
+                mUserId);
     }
 
     @Test
@@ -121,12 +130,17 @@
     public void testChangePassword() throws Exception {
         when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
         when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
-        when(mLockPatternUtils.checkPassword("1234".getBytes(), mUserId)).thenReturn(true);
+        when(mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)).thenReturn(
+                PASSWORD_QUALITY_ALPHABETIC);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPassword("1234"), mUserId, null)).thenReturn(true);
         assertEquals(0,  mCommand.exec(new Binder(), in, out, err,
                 new String[] { "set-password", "--old", "1234", "4321" },
                 mShellCallback, mResultReceiver));
-        verify(mLockPatternUtils).saveLockPassword("4321".getBytes(), "1234".getBytes(),
-                PASSWORD_QUALITY_ALPHABETIC, mUserId);
+        verify(mLockPatternUtils).setLockCredential(
+                LockscreenCredential.createPassword("4321"),
+                LockscreenCredential.createPassword("1234"),
+                mUserId);
     }
 
     @Test
@@ -143,11 +157,15 @@
     public void testChangePattern() throws Exception {
         when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
         when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
-        when(mLockPatternUtils.checkPattern(stringToPattern("1234"), mUserId)).thenReturn(true);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPattern(stringToPattern("1234")),
+                mUserId, null)).thenReturn(true);
         assertEquals(0, mCommand.exec(new Binder(), in, out, err,
                 new String[] { "set-pattern", "--old", "1234", "4321" },
                 mShellCallback, mResultReceiver));
-        verify(mLockPatternUtils).saveLockPattern(stringToPattern("4321"), "1234".getBytes(),
+        verify(mLockPatternUtils).setLockCredential(
+                LockscreenCredential.createPattern(stringToPattern("4321")),
+                LockscreenCredential.createPattern(stringToPattern("1234")),
                 mUserId);
     }
 
@@ -165,10 +183,19 @@
     public void testClear() throws Exception {
         when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
         when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
-        when(mLockPatternUtils.checkPattern(stringToPattern("1234"), mUserId)).thenReturn(true);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPattern(stringToPattern("1234")),
+                mUserId, null)).thenReturn(true);
         assertEquals(0, mCommand.exec(new Binder(), in, out, err,
                 new String[] { "clear", "--old", "1234" },
                 mShellCallback, mResultReceiver));
-        verify(mLockPatternUtils).clearLock("1234".getBytes(), mUserId);
+        verify(mLockPatternUtils).setLockCredential(
+                LockscreenCredential.createNone(),
+                LockscreenCredential.createPattern(stringToPattern("1234")),
+                mUserId);
+    }
+
+    private List<LockPatternView.Cell> stringToPattern(String str) {
+        return LockPatternUtils.byteArrayToPattern(str.getBytes());
     }
 }
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 2a169b7..cb51897 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
@@ -434,35 +434,6 @@
         assertEquals(2, PersistentData.TYPE_SP_WEAVER);
     }
 
-    public void testCredentialHash_serializeUnserialize() {
-        byte[] serialized = CredentialHash.create(
-                PAYLOAD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD).toBytes();
-        CredentialHash deserialized = CredentialHash.fromBytes(serialized);
-
-        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, deserialized.type);
-        assertArrayEquals(PAYLOAD, deserialized.hash);
-    }
-
-    public void testCredentialHash_unserialize_versionGatekeeper() {
-        // This test ensures that we can read serialized VERSION_GATEKEEPER CredentialHashes
-        // even if we change the wire format in the future.
-        byte[] serialized = new byte[] {
-                1, /* VERSION_GATEKEEPER */
-                2, /* CREDENTIAL_TYPE_PASSWORD */
-                0, 0, 0, 5, /* hash length */
-                1, 2, -1, -2, 33, /* hash */
-        };
-        CredentialHash deserialized = CredentialHash.fromBytes(serialized);
-
-        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, deserialized.type);
-        assertArrayEquals(PAYLOAD, deserialized.hash);
-
-        // Make sure the constants we use on the wire do not change.
-        assertEquals(-1, LockPatternUtils.CREDENTIAL_TYPE_NONE);
-        assertEquals(1, LockPatternUtils.CREDENTIAL_TYPE_PATTERN);
-        assertEquals(2, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
-    }
-
     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/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 0776589..42ca42a 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -39,6 +39,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockscreenCredential;
 import com.android.internal.widget.VerifyCredentialResponse;
 import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult;
 import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken;
@@ -364,7 +365,7 @@
         // Verify DPM gets notified about new device lock
         flushHandlerTasks();
         final PasswordMetrics metric = PasswordMetrics.computeForCredential(
-                LockPatternUtils.CREDENTIAL_TYPE_PATTERN, pattern);
+                LockscreenCredential.createPattern(LockPatternUtils.byteArrayToPattern(pattern)));
         assertEquals(metric, mService.getUserPasswordMetrics(PRIMARY_USER_ID));
         verify(mDevicePolicyManager).reportPasswordChanged(PRIMARY_USER_ID);
 
@@ -512,7 +513,7 @@
         assertFalse(mService.havePattern(PRIMARY_USER_ID));
     }
 
-    public void testgetHashFactorPrimaryUser() throws RemoteException {
+    public void testGetHashFactorPrimaryUser() throws RemoteException {
         final byte[] password = "password".getBytes();
         mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
                 PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
@@ -527,7 +528,7 @@
         assertArrayEquals(hashFactor, newHashFactor);
     }
 
-    public void testgetHashFactorManagedProfileUnifiedChallenge() throws RemoteException {
+    public void testGetHashFactorManagedProfileUnifiedChallenge() throws RemoteException {
         final byte[] pattern = "1236".getBytes();
         mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
                 null, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID, false);
@@ -535,7 +536,7 @@
         assertNotNull(mService.getHashFactor(null, MANAGED_PROFILE_USER_ID));
     }
 
-    public void testgetHashFactorManagedProfileSeparateChallenge() throws RemoteException {
+    public void testGetHashFactorManagedProfileSeparateChallenge() throws RemoteException {
         final byte[] primaryPassword = "primary".getBytes();
         final byte[] profilePassword = "profile".getBytes();
         mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
diff --git a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
index fe7a376..25b41db 100644
--- a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
@@ -29,7 +29,6 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.SystemClock;
-import android.provider.Settings;
 import android.support.test.uiautomator.UiDevice;
 import android.text.TextUtils;
 import android.util.Log;
@@ -88,17 +87,11 @@
 
     private static final int REPEAT_TEST_COUNT = 5;
 
-    private static final String KEY_PAROLE_DURATION = "parole_duration";
-    private static final String DESIRED_PAROLE_DURATION = "0";
-
     private static Context mContext;
     private static UiDevice mUiDevice;
     private static int mTestPkgUid;
     private static BatteryManager mBatteryManager;
 
-    private static boolean mAppIdleConstsUpdated;
-    private static String mOriginalAppIdleConsts;
-
     private static ServiceConnection mServiceConnection;
     private static ICmdReceiverService mCmdReceiverService;
 
@@ -107,7 +100,6 @@
         mContext = InstrumentationRegistry.getContext();
         mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
 
-        setDesiredParoleDuration();
         mContext.getPackageManager().setApplicationEnabledSetting(TEST_PKG,
                 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
         mTestPkgUid = mContext.getPackageManager().getPackageUid(TEST_PKG, 0);
@@ -119,10 +111,6 @@
     @AfterClass
     public static void tearDownOnce() throws Exception {
         batteryReset();
-        if (mAppIdleConstsUpdated) {
-            Settings.Global.putString(mContext.getContentResolver(),
-                    Settings.Global.APP_IDLE_CONSTANTS, mOriginalAppIdleConsts);
-        }
         unbindService();
     }
 
@@ -160,27 +148,6 @@
         }
     }
 
-    private static void setDesiredParoleDuration() {
-        mOriginalAppIdleConsts = Settings.Global.getString(mContext.getContentResolver(),
-                Settings.Global.APP_IDLE_CONSTANTS);
-        String newAppIdleConstants;
-        final String newConstant = KEY_PAROLE_DURATION + "=" + DESIRED_PAROLE_DURATION;
-        if (mOriginalAppIdleConsts == null || "null".equals(mOriginalAppIdleConsts)) {
-            // app_idle_constants is initially empty, so just assign the desired value.
-            newAppIdleConstants = newConstant;
-        } else if (mOriginalAppIdleConsts.contains(KEY_PAROLE_DURATION)) {
-            // app_idle_constants contains parole_duration, so replace it with the desired value.
-            newAppIdleConstants = mOriginalAppIdleConsts.replaceAll(
-                    KEY_PAROLE_DURATION + "=\\d+", newConstant);
-        } else {
-            // app_idle_constants didn't have parole_duration, so append the desired value.
-            newAppIdleConstants = mOriginalAppIdleConsts + "," + newConstant;
-        }
-        Settings.Global.putString(mContext.getContentResolver(),
-                Settings.Global.APP_IDLE_CONSTANTS, newAppIdleConstants);
-        mAppIdleConstsUpdated = true;
-    }
-
     @Test
     public void testStartActivity_batterySaver() throws Exception {
         setBatterySaverMode(true);
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 ba12b73..8a48904 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -113,6 +113,7 @@
 import android.net.NetworkTemplate;
 import android.net.StringNetworkSpecifier;
 import android.os.Binder;
+import android.os.Handler;
 import android.os.INetworkManagementService;
 import android.os.PersistableBundle;
 import android.os.PowerManagerInternal;
@@ -1117,7 +1118,7 @@
         // Define simple data plan
         final SubscriptionPlan plan = buildMonthlyDataPlan(
                 ZonedDateTime.parse("2015-11-01T00:00:00.00Z"), DataUnit.MEGABYTES.toBytes(1800));
-        mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[] { plan },
+        setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[] { plan },
                 mServiceContext.getOpPackageName());
 
         // We're 20% through the month (6 days)
@@ -1241,7 +1242,7 @@
         // Define simple data plan which gives us effectively 60MB/day
         final SubscriptionPlan plan = buildMonthlyDataPlan(
                 ZonedDateTime.parse("2015-11-01T00:00:00.00Z"), DataUnit.MEGABYTES.toBytes(1800));
-        mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[] { plan },
+        setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[] { plan },
                 mServiceContext.getOpPackageName());
 
         // We're 20% through the month (6 days)
@@ -1457,6 +1458,8 @@
         when(mConnManager.getAllNetworkState()).thenReturn(new NetworkState[0]);
         when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[]{FAKE_SUB_ID});
         when(mTelephonyManager.getSubscriberId(FAKE_SUB_ID)).thenReturn(FAKE_SUBSCRIBER_ID);
+        when(mTelephonyManager.createForSubscriptionId(FAKE_SUB_ID))
+                .thenReturn(mock(TelephonyManager.class));
         PersistableBundle bundle = CarrierConfigManager.getDefaultConfig();
         when(mCarrierConfigManager.getConfigForSubId(FAKE_SUB_ID)).thenReturn(bundle);
         setNetworkPolicies(buildDefaultFakeMobilePolicy());
@@ -1468,6 +1471,8 @@
         when(mConnManager.getAllNetworkState()).thenReturn(new NetworkState[0]);
         when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[]{FAKE_SUB_ID});
         when(mTelephonyManager.getSubscriberId(FAKE_SUB_ID)).thenReturn(FAKE_SUBSCRIBER_ID);
+        when(mTelephonyManager.createForSubscriptionId(FAKE_SUB_ID))
+                .thenReturn(mock(TelephonyManager.class));
         when(mCarrierConfigManager.getConfigForSubId(FAKE_SUB_ID)).thenReturn(null);
         setNetworkPolicies(buildDefaultFakeMobilePolicy());
         // smoke test to make sure no errors are raised
@@ -1653,7 +1658,7 @@
             final SubscriptionPlan plan = buildMonthlyDataPlan(
                     ZonedDateTime.parse("2015-11-01T00:00:00.00Z"),
                     DataUnit.MEGABYTES.toBytes(1800));
-            mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
+            setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
                     mServiceContext.getOpPackageName());
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
@@ -1674,7 +1679,7 @@
             final SubscriptionPlan plan = buildMonthlyDataPlan(
                     ZonedDateTime.parse("2015-11-01T00:00:00.00Z"),
                     DataUnit.MEGABYTES.toBytes(100));
-            mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
+            setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
                     mServiceContext.getOpPackageName());
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
@@ -1690,7 +1695,7 @@
         {
             final SubscriptionPlan plan = buildMonthlyDataPlan(
                     ZonedDateTime.parse("2015-11-01T00:00:00.00Z"), BYTES_UNLIMITED);
-            mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
+            setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
                     mServiceContext.getOpPackageName());
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
@@ -1707,7 +1712,7 @@
         {
             final SubscriptionPlan plan = buildMonthlyDataPlan(
                     ZonedDateTime.parse("2015-11-01T00:00:00.00Z"), BYTES_UNLIMITED);
-            mService.setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
+            setSubscriptionPlans(TEST_SUB_ID, new SubscriptionPlan[]{plan},
                     mServiceContext.getOpPackageName());
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
@@ -1923,6 +1928,8 @@
         when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(
                 new int[] { TEST_SUB_ID });
         when(mTelephonyManager.getSubscriberId(TEST_SUB_ID)).thenReturn(TEST_IMSI);
+        when(mTelephonyManager.createForSubscriptionId(TEST_SUB_ID))
+                .thenReturn(mock(TelephonyManager.class));
         doNothing().when(mTelephonyManager).setPolicyDataEnabled(anyBoolean(), anyInt());
         expectNetworkState(false /* roaming */);
     }
@@ -2049,6 +2056,23 @@
 
     private FutureIntent mRestrictBackgroundChanged;
 
+    private void postMsgAndWaitForCompletion() throws InterruptedException {
+        final Handler handler = mService.getHandlerForTesting();
+        final CountDownLatch latch = new CountDownLatch(1);
+        mService.getHandlerForTesting().post(latch::countDown);
+        if (!latch.await(5, TimeUnit.SECONDS)) {
+            fail("Timed out waiting for the test msg to be handled");
+        }
+    }
+
+    private void setSubscriptionPlans(int subId, SubscriptionPlan[] plans, String callingPackage)
+            throws InterruptedException {
+        mService.setSubscriptionPlans(subId, plans, callingPackage);
+        // setSubscriptionPlans() triggers async events, wait for those to be completed before
+        // moving forward as they could interfere with the tests later.
+        postMsgAndWaitForCompletion();
+    }
+
     private void setRestrictBackground(boolean flag) throws Exception {
         mService.setRestrictBackground(flag);
         // Sanity check.
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulCrcsTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulCrcsTests.java
new file mode 100644
index 0000000..23f1281
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulCrcsTests.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net.watchlist;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.HexDump;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+/**
+ * runtest frameworks-services -c com.android.server.net.watchlist.HarmfulCrcTests
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class HarmfulCrcsTests {
+
+    private static final byte[] TEST_DIGEST = HexDump.hexStringToByteArray("AABBCCDD");
+
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void testHarmfulCrcs_setAndContains() throws Exception {
+        HarmfulCrcs harmfulCrcs = new HarmfulCrcs(
+                Arrays.asList(new byte[][] {TEST_DIGEST}));
+        assertTrue(harmfulCrcs.contains(0xaabbccdd));
+        assertFalse(harmfulCrcs.contains(0xbbbbbbbb));
+        assertFalse(harmfulCrcs.contains(0x01020304));
+        assertFalse(harmfulCrcs.contains(0xddccbbaa));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
index 43bcd4f..3c10447 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -165,8 +165,8 @@
                 /* stagingManager */ null,
                 /* sessionId */ sessionId,
                 /* userId */  456,
-                /* installerPackageName */ "testInstaller",
                 /* installerUid */ -1,
+                /* installSource */ InstallSource.create("testInstaller", "testInstaller"),
                 /* sessionParams */ params,
                 /* createdMillis */ 0L,
                 /* stageDir */ mTmpDir,
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 15032c5..1106be2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -812,11 +812,9 @@
         assertSame(origPkgSetting.cpuAbiOverrideString, testPkgSetting.cpuAbiOverrideString);
         assertThat(origPkgSetting.cpuAbiOverrideString, is(testPkgSetting.cpuAbiOverrideString));
         assertThat(origPkgSetting.firstInstallTime, is(testPkgSetting.firstInstallTime));
-        assertSame(origPkgSetting.installerPackageName, testPkgSetting.installerPackageName);
-        assertThat(origPkgSetting.installerPackageName, is(testPkgSetting.installerPackageName));
+        assertSame(origPkgSetting.installSource, testPkgSetting.installSource);
         assertThat(origPkgSetting.installPermissionsFixed,
                 is(testPkgSetting.installPermissionsFixed));
-        assertThat(origPkgSetting.isOrphaned, is(testPkgSetting.isOrphaned));
         assertSame(origPkgSetting.keySetData, testPkgSetting.keySetData);
         assertThat(origPkgSetting.keySetData, is(testPkgSetting.keySetData));
         assertThat(origPkgSetting.lastUpdateTime, is(testPkgSetting.lastUpdateTime));
diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
index 05905d9..3ea3b3c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
@@ -429,7 +429,7 @@
 
         final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
 
-        assertThat(scanResult.pkgSetting.isOrphaned, is(true));
+        assertThat(scanResult.pkgSetting.installSource.isOrphaned, is(true));
     }
 
     private static Matcher<Integer> hasFlag(final int flag) {
diff --git a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
index 0c5451f..a83d940 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
@@ -106,6 +106,11 @@
         return createPackageRollbackInfo(packageName, new int[] {});
     }
 
+    private static Rollback createRollbackForId(int rollbackId) {
+        return new Rollback(rollbackId, new File("/does/not/exist"), -1,
+                0, "com.xyz");
+    }
+
     @Test
     public void testRestoreAppDataSnapshot_pendingBackupForUser() throws Exception {
         Installer installer = mock(Installer.class);
@@ -232,18 +237,16 @@
         wasRecentlyRestored.getPendingRestores().add(
                 new RestoreInfo(73 /* userId */, 239 /* appId*/, "seInfo"));
 
-        Rollback dataWithPendingBackup = new Rollback(101, new File("/does/not/exist"), -1);
+        Rollback dataWithPendingBackup = createRollbackForId(101);
         dataWithPendingBackup.info.getPackages().add(pendingBackup);
 
-        Rollback dataWithRecentRestore = new Rollback(17239, new File("/does/not/exist"),
-                -1);
+        Rollback dataWithRecentRestore = createRollbackForId(17239);
         dataWithRecentRestore.info.getPackages().add(wasRecentlyRestored);
 
-        Rollback dataForDifferentUser = new Rollback(17239, new File("/does/not/exist"),
-                -1);
+        Rollback dataForDifferentUser = createRollbackForId(17239);
         dataForDifferentUser.info.getPackages().add(ignoredInfo);
 
-        Rollback dataForRestore = new Rollback(17239, new File("/does/not/exist"), -1);
+        Rollback dataForRestore = createRollbackForId(17239);
         dataForRestore.info.getPackages().add(pendingRestore);
         dataForRestore.info.getPackages().add(wasRecentlyRestored);
 
diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
index ee3b15a..aec489c 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
@@ -43,6 +43,8 @@
 public class RollbackStoreTest {
 
     private static final int ID = 123;
+    private static final int USER = 0;
+    private static final String INSTALLER = "some.installer";
 
     private static final Correspondence<VersionedPackage, VersionedPackage> VER_PKG_CORR =
             new Correspondence<VersionedPackage, VersionedPackage>() {
@@ -97,7 +99,8 @@
             + "'longVersionCode':23},{'packageName':'something','longVersionCode':999}],"
             + "'committedSessionId':45654465},'timestamp':'2019-10-01T12:29:08.855Z',"
             + "'stagedSessionId':-1,'state':'enabling','apkSessionId':-1,"
-            + "'restoreUserDataInProgress':true}";
+            + "'restoreUserDataInProgress':true, 'userId':0,"
+            + "'installerPackageName':'some.installer'}";
 
     @Rule
     public TemporaryFolder mFolder = new TemporaryFolder();
@@ -115,7 +118,7 @@
 
     @Test
     public void createNonStaged() {
-        Rollback rollback = mRollbackStore.createNonStagedRollback(ID);
+        Rollback rollback = mRollbackStore.createNonStagedRollback(ID, USER, INSTALLER);
 
         assertThat(rollback.getBackupDir().getAbsolutePath())
                 .isEqualTo(mFolder.getRoot().getAbsolutePath() + "/" + ID);
@@ -128,7 +131,7 @@
 
     @Test
     public void createStaged() {
-        Rollback rollback = mRollbackStore.createStagedRollback(ID, 897);
+        Rollback rollback = mRollbackStore.createStagedRollback(ID, 897, USER, INSTALLER);
 
         assertThat(rollback.getBackupDir().getAbsolutePath())
                 .isEqualTo(mFolder.getRoot().getAbsolutePath() + "/" + ID);
@@ -143,7 +146,7 @@
 
     @Test
     public void saveAndLoadRollback() {
-        Rollback origRb = mRollbackStore.createNonStagedRollback(ID);
+        Rollback origRb = mRollbackStore.createNonStagedRollback(ID, USER, INSTALLER);
 
         origRb.setRestoreUserDataInProgress(true);
         origRb.info.getCausePackages().add(new VersionedPackage("com.made.up", 2));
@@ -193,7 +196,7 @@
 
     @Test
     public void loadFromJson() throws Exception {
-        Rollback expectedRb = mRollbackStore.createNonStagedRollback(ID);
+        Rollback expectedRb = mRollbackStore.createNonStagedRollback(ID, USER, INSTALLER);
 
         expectedRb.setTimestamp(Instant.parse("2019-10-01T12:29:08.855Z"));
         expectedRb.setRestoreUserDataInProgress(true);
@@ -242,7 +245,7 @@
 
     @Test
     public void saveAndDelete() {
-        Rollback rollback = mRollbackStore.createNonStagedRollback(ID);
+        Rollback rollback = mRollbackStore.createNonStagedRollback(ID, USER, INSTALLER);
 
         RollbackStore.saveRollback(rollback);
 
@@ -287,6 +290,9 @@
             assertPackageRollbacksAreEquivalent(
                     b.info.getPackages().get(i), a.info.getPackages().get(i));
         }
+
+        assertThat(a.getUserId()).isEqualTo(b.getUserId());
+        assertThat(a.getInstallerPackageName()).isEqualTo(b.getInstallerPackageName());
     }
 
     private void assertPackageRollbacksAreEquivalent(PackageRollbackInfo b, PackageRollbackInfo a) {
diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java
index 151b6e2..e368d63 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java
@@ -52,6 +52,8 @@
     private static final String PKG_2 = "test.testpackage.pkg2";
     private static final String PKG_3 = "com.blah.hello.three";
     private static final String PKG_4 = "com.something.4pack";
+    private static final int USER = 0;
+    private static final String INSTALLER = "some.installer";
 
     @Mock private AppDataRollbackHelper mMockDataHelper;
 
@@ -66,7 +68,7 @@
         int sessionId = 567;
         File file = new File("/test/testing");
 
-        Rollback rollback = new Rollback(rollbackId, file, sessionId);
+        Rollback rollback = new Rollback(rollbackId, file, sessionId, USER, INSTALLER);
 
         assertThat(rollback.isEnabling()).isTrue();
         assertThat(rollback.getBackupDir().getAbsolutePath()).isEqualTo("/test/testing");
@@ -79,7 +81,7 @@
         int rollbackId = 123;
         File file = new File("/test/testing");
 
-        Rollback rollback = new Rollback(rollbackId, file, -1);
+        Rollback rollback = new Rollback(rollbackId, file, -1, USER, INSTALLER);
 
         assertThat(rollback.isEnabling()).isTrue();
         assertThat(rollback.getBackupDir().getAbsolutePath()).isEqualTo("/test/testing");
@@ -88,7 +90,8 @@
 
     @Test
     public void rollbackMadeAvailable() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER,
+                INSTALLER);
 
         assertThat(rollback.isEnabling()).isTrue();
         assertThat(rollback.isAvailable()).isFalse();
@@ -106,7 +109,7 @@
 
     @Test
     public void deletedRollbackCannotBeMadeAvailable() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
 
         rollback.delete(mMockDataHelper);
 
@@ -120,7 +123,7 @@
 
     @Test
     public void getPackageNamesAllAndJustApex() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 11, true);
         PackageRollbackInfo pkgInfo3 = newPkgInfoFor(PKG_3, 19, 1, false);
@@ -134,7 +137,7 @@
 
     @Test
     public void includesPackagesAfterEnable() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         PackageRollbackInfo pkgInfo3 = newPkgInfoFor(PKG_3, 157, 156, false);
@@ -162,7 +165,7 @@
 
     @Test
     public void snapshotWhenEnabling() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
@@ -180,7 +183,7 @@
 
     @Test
     public void snapshotWhenAvailable() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
@@ -201,7 +204,7 @@
 
     @Test
     public void snapshotWhenDeleted() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
@@ -222,7 +225,7 @@
 
     @Test
     public void snapshotThenDelete() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
@@ -242,7 +245,7 @@
 
     @Test
     public void restoreUserDataDoesNothingIfNotInProgress() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
@@ -257,7 +260,7 @@
 
     @Test
     public void restoreUserDataDoesNothingIfPackageNotFound() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
@@ -273,7 +276,7 @@
 
     @Test
     public void restoreUserDataRestoresIfInProgressAndPackageFound() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 4ffcf8f..12ba219 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -47,7 +47,6 @@
 
 import android.app.usage.AppStandbyInfo;
 import android.app.usage.UsageEvents;
-import android.app.usage.UsageStatsManagerInternal;
 import android.appwidget.AppWidgetManager;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -77,7 +76,6 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -108,8 +106,6 @@
     private static final long WORKING_SET_THRESHOLD = 12 * HOUR_MS;
     private static final long FREQUENT_THRESHOLD = 24 * HOUR_MS;
     private static final long RARE_THRESHOLD = 48 * HOUR_MS;
-    // Short STABLE_CHARGING_THRESHOLD for testing purposes
-    private static final long STABLE_CHARGING_THRESHOLD = 2000;
 
     /** Mock variable used in {@link MyInjector#isPackageInstalled(String, int, int)} */
     private static boolean isPackageInstalled = true;
@@ -132,7 +128,6 @@
     static class MyInjector extends AppStandbyController.Injector {
         long mElapsedRealtime;
         boolean mIsAppIdleEnabled = true;
-        boolean mIsCharging;
         List<String> mPowerSaveWhitelistExceptIdle = new ArrayList<>();
         boolean mDisplayOn;
         DisplayManager.DisplayListener mDisplayListener;
@@ -167,11 +162,6 @@
         }
 
         @Override
-        boolean isCharging() {
-            return mIsCharging;
-        }
-
-        @Override
         boolean isPowerSaveWhitelistExceptIdleApp(String packageName) throws RemoteException {
             return mPowerSaveWhitelistExceptIdle.contains(packageName);
         }
@@ -228,8 +218,7 @@
             return "screen_thresholds=0/0/0/" + HOUR_MS + ",elapsed_thresholds=0/"
                     + WORKING_SET_THRESHOLD + "/"
                     + FREQUENT_THRESHOLD + "/"
-                    + RARE_THRESHOLD + ","
-                    + "stable_charging_threshold=" + STABLE_CHARGING_THRESHOLD;
+                    + RARE_THRESHOLD;
         }
 
         @Override
@@ -273,13 +262,6 @@
         } catch (PackageManager.NameNotFoundException nnfe) {}
     }
 
-    private void setChargingState(AppStandbyController controller, boolean charging) {
-        mInjector.mIsCharging = charging;
-        if (controller != null) {
-            controller.setChargingState(charging);
-        }
-    }
-
     private void setAppIdleEnabled(AppStandbyController controller, boolean enabled) {
         mInjector.mIsAppIdleEnabled = enabled;
         if (controller != null) {
@@ -296,7 +278,6 @@
         controller.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
         mInjector.setDisplayOn(false);
         mInjector.setDisplayOn(true);
-        setChargingState(controller, false);
         controller.checkIdleStates(USER_ID);
         assertNotEquals(STANDBY_BUCKET_EXEMPTED,
                 controller.getAppStandbyBucket(PACKAGE_1, USER_ID,
@@ -314,65 +295,6 @@
         MyContextWrapper myContext = new MyContextWrapper(InstrumentationRegistry.getContext());
         mInjector = new MyInjector(myContext, Looper.getMainLooper());
         mController = setupController();
-        setChargingState(mController, false);
-    }
-
-    private class TestParoleListener extends UsageStatsManagerInternal.AppIdleStateChangeListener {
-        private boolean mOnParole = false;
-        private CountDownLatch mLatch;
-        private long mLastParoleChangeTime;
-        private boolean mIsExpecting = false;
-        private boolean mExpectedParoleState;
-
-        public boolean getParoleState() {
-            synchronized (this) {
-                return mOnParole;
-            }
-        }
-
-        public void rearmLatch() {
-            synchronized (this) {
-                mLatch = new CountDownLatch(1);
-                mIsExpecting = false;
-            }
-        }
-
-        public void rearmLatch(boolean expectedParoleState) {
-            synchronized (this) {
-                mLatch = new CountDownLatch(1);
-                mIsExpecting = true;
-                mExpectedParoleState = expectedParoleState;
-            }
-        }
-
-        public void awaitOnLatch(long time) throws Exception {
-            mLatch.await(time, TimeUnit.MILLISECONDS);
-        }
-
-        public long getLastParoleChangeTime() {
-            synchronized (this) {
-                return mLastParoleChangeTime;
-            }
-        }
-
-        @Override
-        public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
-                int bucket, int reason) {
-        }
-
-        @Override
-        public void onParoleStateChanged(boolean isParoleOn) {
-            synchronized (this) {
-                // Only record information if it is being looked for
-                if (mLatch != null && mLatch.getCount() > 0) {
-                    mOnParole = isParoleOn;
-                    mLastParoleChangeTime = getCurrentTime();
-                    if (!mIsExpecting || isParoleOn == mExpectedParoleState) {
-                        mLatch.countDown();
-                    }
-                }
-            }
-        }
     }
 
     @Test
@@ -383,133 +305,6 @@
                         mInjector.mElapsedRealtime, false));
     }
 
-    @Test
-    public void testCharging() throws Exception {
-        long startTime;
-        TestParoleListener paroleListener = new TestParoleListener();
-        long marginOfError = 200;
-
-        // Charging
-        paroleListener.rearmLatch();
-        mController.addListener(paroleListener);
-        startTime = getCurrentTime();
-        setChargingState(mController, true);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-        // Parole will only be granted after device has been charging for a sufficient amount of
-        // time.
-        assertEquals(STABLE_CHARGING_THRESHOLD,
-                paroleListener.getLastParoleChangeTime() - startTime,
-                marginOfError);
-
-        // Discharging
-        paroleListener.rearmLatch();
-        startTime = getCurrentTime();
-        setChargingState(mController, false);
-        mController.checkIdleStates(USER_ID);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertFalse(paroleListener.getParoleState());
-        // Parole should be revoked immediately
-        assertEquals(0,
-                paroleListener.getLastParoleChangeTime() - startTime,
-                marginOfError);
-
-        // Brief Charging
-        paroleListener.rearmLatch();
-        setChargingState(mController, true);
-        setChargingState(mController, false);
-        // Device stopped charging before the stable charging threshold.
-        // Parole should not be granted at the end of the threshold
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertFalse(paroleListener.getParoleState());
-
-        // Charging Again
-        paroleListener.rearmLatch();
-        startTime = getCurrentTime();
-        setChargingState(mController, true);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.getParoleState());
-        assertTrue(paroleListener.mOnParole);
-        assertEquals(STABLE_CHARGING_THRESHOLD,
-                paroleListener.getLastParoleChangeTime() - startTime,
-                marginOfError);
-    }
-
-    @Test
-    public void testEnabledState() throws Exception {
-        TestParoleListener paroleListener = new TestParoleListener();
-        paroleListener.rearmLatch(true);
-        mController.addListener(paroleListener);
-        long lastUpdateTime;
-
-        // Test that listeners are notified if enabled changes when the device is not in parole.
-        setChargingState(mController, false);
-
-        // Start off not enabled. Device is effectively in permanent parole.
-        setAppIdleEnabled(mController, false);
-        // Since AppStandbyController uses a handler to notify listeners of a state change, there is
-        // some inherent latency between changing the state and getting the notification. We need to
-        // wait until the paroleListener has been notified that parole is on before continuing with
-        // the test.
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-
-        // Enable controller
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, true);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertFalse(paroleListener.mOnParole);
-        lastUpdateTime = paroleListener.getLastParoleChangeTime();
-
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, true);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertFalse(paroleListener.mOnParole);
-        // Make sure AppStandbyController doesn't notify listeners when there's no change.
-        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
-
-        // Disable controller
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, false);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-        lastUpdateTime = paroleListener.getLastParoleChangeTime();
-
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, false);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-        // Make sure AppStandbyController doesn't notify listeners when there's no change.
-        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
-
-
-        // Test that listeners aren't notified if enabled status changes when the device is already
-        // in parole.
-
-        // A device is in parole whenever it's charging.
-        setChargingState(mController, true);
-
-        // Start off not enabled.
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, false);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-        lastUpdateTime = paroleListener.getLastParoleChangeTime();
-
-        // Test that toggling doesn't notify the listener.
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, true);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
-
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, false);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
-    }
-
     private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket) {
         mInjector.mElapsedRealtime = elapsedTime;
         controller.checkIdleStates(USER_ID);
@@ -804,8 +599,6 @@
 
     @Test
     public void testSystemInteractionTimeout() throws Exception {
-        setChargingState(mController, false);
-
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
         // Fast forward to RARE
         mInjector.mElapsedRealtime = RARE_THRESHOLD + 100;
@@ -829,8 +622,6 @@
 
     @Test
     public void testInitialForegroundServiceTimeout() throws Exception {
-        setChargingState(mController, false);
-
         mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100;
         // Make sure app is in NEVER bucket
         mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 8c3373f..1e55b15 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -22,6 +22,8 @@
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
+import static android.media.AudioAttributes.USAGE_NOTIFICATION;
+import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
 
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNull;
@@ -105,6 +107,7 @@
     private int mUid = 1000;
     private int mPid = 2000;
     private android.os.UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
+    private NotificationChannel mChannel;
 
     private VibrateRepeatMatcher mVibrateOnceMatcher = new VibrateRepeatMatcher(-1);
     private VibrateRepeatMatcher mVibrateLoopMatcher = new VibrateRepeatMatcher(0);
@@ -158,6 +161,8 @@
         mService.mScreenOn = false;
         mService.mInCallStateOffHook = false;
         mService.mNotificationPulseEnabled = true;
+
+        mChannel = new NotificationChannel("test", "test", IMPORTANCE_HIGH);
     }
 
     //
@@ -174,13 +179,18 @@
                 true /* noisy */, false /* buzzy*/, false /* lights */);
     }
 
+    private NotificationRecord getBeepyOtherNotification() {
+        return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
+                true /* noisy */, false /* buzzy*/, false /* lights */);
+    }
+
     private NotificationRecord getBeepyOnceNotification() {
         return getNotificationRecord(mId, false /* insistent */, true /* once */,
                 true /* noisy */, false /* buzzy*/, false /* lights */);
     }
 
     private NotificationRecord getQuietNotification() {
-        return getNotificationRecord(mId, false /* insistent */, false /* once */,
+        return getNotificationRecord(mId, false /* insistent */, true /* once */,
                 false /* noisy */, false /* buzzy*/, false /* lights */);
     }
 
@@ -214,6 +224,11 @@
                 false /* noisy */, true /* buzzy*/, false /* lights */);
     }
 
+    private NotificationRecord getBuzzyOtherNotification() {
+        return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
+                false /* noisy */, true /* buzzy*/, false /* lights */);
+    }
+
     private NotificationRecord getBuzzyOnceNotification() {
         return getNotificationRecord(mId, false /* insistent */, true /* once */,
                 false /* noisy */, true /* buzzy*/, false /* lights */);
@@ -239,22 +254,34 @@
                 false /* noisy */, false /* buzzy*/, true /* lights */);
     }
 
-    private NotificationRecord getCallRecord(int id, boolean insistent) {
-        return getNotificationRecord(id, false, false /* once */, true /* noisy */,
-                false /* buzzy */, false /* lights */, false /* default vib */,
-                false /* default sound */, false /* default lights */, "",
-                Notification.GROUP_ALERT_ALL, false);
+    private NotificationRecord getCallRecord(int id, NotificationChannel channel, boolean looping) {
+        final Builder builder = new Builder(getContext())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setPriority(Notification.PRIORITY_HIGH);
+        Notification n = builder.build();
+        if (looping) {
+            n.flags |= Notification.FLAG_INSISTENT;
+        }
+        StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid,
+                mPid, n, mUser, null, System.currentTimeMillis());
+        NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
+        mService.addNotification(r);
+
+        return r;
     }
 
     private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
             boolean noisy, boolean buzzy, boolean lights) {
-        return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, true, true, true,
-                null, Notification.GROUP_ALERT_ALL, false);
+        return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, buzzy, noisy,
+                lights, null, Notification.GROUP_ALERT_ALL, false);
     }
 
-    private NotificationRecord getLeanbackNotificationRecord(int id, boolean insistent, boolean once,
+    private NotificationRecord getLeanbackNotificationRecord(int id, boolean insistent,
+            boolean once,
             boolean noisy, boolean buzzy, boolean lights) {
-        return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, true, true, true,
+        return getNotificationRecord(id, insistent, once, noisy, buzzy, lights, true, true,
+                true,
                 null, Notification.GROUP_ALERT_ALL, true);
     }
 
@@ -265,16 +292,16 @@
 
     private NotificationRecord getLightsNotificationRecord(String groupKey,
             int groupAlertBehavior) {
-        return getNotificationRecord(mId, false, false, false, false, true /*lights*/, true, true,
-                true, groupKey, groupAlertBehavior, false);
+        return getNotificationRecord(mId, false, false, false, false, true /*lights*/, true,
+                true, true, groupKey, groupAlertBehavior, false);
     }
 
-    private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
+    private NotificationRecord getNotificationRecord(int id,
+            boolean insistent, boolean once,
             boolean noisy, boolean buzzy, boolean lights, boolean defaultVibration,
             boolean defaultSound, boolean defaultLights, String groupKey, int groupAlertBehavior,
             boolean isLeanback) {
-        NotificationChannel channel =
-                new NotificationChannel("test", "test", IMPORTANCE_HIGH);
+
         final Builder builder = new Builder(getContext())
                 .setContentTitle("foo")
                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
@@ -285,31 +312,37 @@
         if (noisy) {
             if (defaultSound) {
                 defaults |= Notification.DEFAULT_SOUND;
-                channel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
+                mChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
                         Notification.AUDIO_ATTRIBUTES_DEFAULT);
             } else {
                 builder.setSound(CUSTOM_SOUND);
-                channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
+                mChannel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
             }
         } else {
-            channel.setSound(null, null);
+            mChannel.setSound(null, null);
         }
         if (buzzy) {
             if (defaultVibration) {
                 defaults |= Notification.DEFAULT_VIBRATE;
             } else {
                 builder.setVibrate(CUSTOM_VIBRATION);
-                channel.setVibrationPattern(CUSTOM_VIBRATION);
+                mChannel.setVibrationPattern(CUSTOM_VIBRATION);
             }
-            channel.enableVibration(true);
+            mChannel.enableVibration(true);
+        } else {
+            mChannel.setVibrationPattern(null);
+            mChannel.enableVibration(false);
         }
+
         if (lights) {
             if (defaultLights) {
                 defaults |= Notification.DEFAULT_LIGHTS;
             } else {
                 builder.setLights(CUSTOM_LIGHT_COLOR, CUSTOM_LIGHT_ON, CUSTOM_LIGHT_OFF);
             }
-            channel.enableLights(true);
+            mChannel.enableLights(true);
+        } else {
+            mChannel.enableLights(false);
         }
         builder.setDefaults(defaults);
 
@@ -329,7 +362,7 @@
 
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid,
                 mPid, n, mUser, null, System.currentTimeMillis());
-        NotificationRecord r = new NotificationRecord(context, sbn, channel);
+        NotificationRecord r = new NotificationRecord(context, sbn, mChannel);
         mService.addNotification(r);
         return r;
     }
@@ -339,18 +372,19 @@
     //
 
     private void verifyNeverBeep() throws RemoteException {
-        verify(mRingtonePlayer, never()).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
-                anyBoolean(), (AudioAttributes) anyObject());
+        verify(mRingtonePlayer, never()).playAsync(any(), any(), anyBoolean(), any());
     }
 
-    private void verifyBeep() throws RemoteException {
-        verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
-                eq(true), (AudioAttributes) anyObject());
+    private void verifyBeepUnlooped() throws RemoteException  {
+        verify(mRingtonePlayer, times(1)).playAsync(any(), any(), eq(false), any());
     }
 
-    private void verifyBeepLooped() throws RemoteException {
-        verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
-                eq(false), (AudioAttributes) anyObject());
+    private void verifyBeepLooped() throws RemoteException  {
+        verify(mRingtonePlayer, times(1)).playAsync(any(), any(), eq(true), any());
+    }
+
+    private void verifyBeep(int times)  throws RemoteException  {
+        verify(mRingtonePlayer, times(times)).playAsync(any(), any(), anyBoolean(), any());
     }
 
     private void verifyNeverStopAudio() throws RemoteException {
@@ -362,24 +396,31 @@
     }
 
     private void verifyNeverVibrate() {
-        verify(mVibrator, never()).vibrate(anyInt(), anyString(), (VibrationEffect) anyObject(),
-                anyString(), (AudioAttributes) anyObject());
+        verify(mVibrator, never()).vibrate(anyInt(), anyString(), any(), anyString(), any());
     }
 
     private void verifyVibrate() {
         verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateOnceMatcher),
-                anyString(), (AudioAttributes) anyObject());
+                anyString(), any());
+    }
+
+    private void verifyVibrate(int times) {
+        verify(mVibrator, times(times)).vibrate(anyInt(), anyString(), any(), anyString(), any());
     }
 
     private void verifyVibrateLooped() {
         verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateLoopMatcher),
-                anyString(), (AudioAttributes) anyObject());
+                anyString(), any());
     }
 
     private void verifyDelayedVibrateLooped() {
         verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
-                argThat(mVibrateLoopMatcher), anyString(),
-                (AudioAttributes) anyObject());
+                argThat(mVibrateLoopMatcher), anyString(), any());
+    }
+
+    private void verifyDelayedVibrate() {
+        verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
+                argThat(mVibrateOnceMatcher), anyString(), any());
     }
 
     private void verifyStopVibrate() {
@@ -398,11 +439,6 @@
         verify(mLight, times(1)).setFlashing(anyInt(), anyInt(), anyInt(), anyInt());
     }
 
-    private void verifyCustomLights() {
-        verify(mLight, times(1)).setFlashing(
-                eq(CUSTOM_LIGHT_COLOR), anyInt(), eq(CUSTOM_LIGHT_ON), eq(CUSTOM_LIGHT_OFF));
-    }
-
     //
     // Tests
     //
@@ -425,7 +461,7 @@
 
         mService.buzzBeepBlinkLocked(r);
 
-        verifyBeepLooped();
+        verifyBeepUnlooped();
         verifyNeverVibrate();
         verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
         assertTrue(r.isInterruptive());
@@ -438,7 +474,7 @@
 
         mService.buzzBeepBlinkLocked(r);
 
-        verifyBeep();
+        verifyBeepLooped();
         assertTrue(r.isInterruptive());
         assertNotEquals(-1, r.getLastAudiblyAlertedMs());
     }
@@ -492,7 +528,7 @@
 
         mService.buzzBeepBlinkLocked(r);
 
-        verifyBeepLooped();
+        verifyBeepUnlooped();
         assertTrue(r.isInterruptive());
     }
 
@@ -533,7 +569,7 @@
         // update should beep
         r.isUpdate = true;
         mService.buzzBeepBlinkLocked(r);
-        verifyBeepLooped();
+        verifyBeepUnlooped();
         verify(mAccessibilityService, times(2)).sendAccessibilityEvent(any(), anyInt());
         assertTrue(r.isInterruptive());
         assertNotEquals(-1, r.getLastAudiblyAlertedMs());
@@ -723,7 +759,7 @@
         mService.buzzBeepBlinkLocked(r);
 
         verifyNeverVibrate();
-        verifyBeepLooped();
+        verifyBeepUnlooped();
         assertTrue(r.isInterruptive());
         assertNotEquals(-1, r.getLastAudiblyAlertedMs());
     }
@@ -821,7 +857,7 @@
 
         mService.buzzBeepBlinkLocked(summary);
 
-        verifyBeepLooped();
+        verifyBeepUnlooped();
         // summaries are never interruptive for notification counts
         assertFalse(summary.isInterruptive());
         assertNotEquals(-1, summary.getLastAudiblyAlertedMs());
@@ -833,7 +869,7 @@
 
         mService.buzzBeepBlinkLocked(nonGroup);
 
-        verifyBeepLooped();
+        verifyBeepUnlooped();
         assertTrue(nonGroup.isInterruptive());
         assertNotEquals(-1, nonGroup.getLastAudiblyAlertedMs());
     }
@@ -856,7 +892,7 @@
 
         mService.buzzBeepBlinkLocked(child);
 
-        verifyBeepLooped();
+        verifyBeepUnlooped();
         assertTrue(child.isInterruptive());
         assertNotEquals(-1, child.getLastAudiblyAlertedMs());
     }
@@ -867,7 +903,7 @@
 
         mService.buzzBeepBlinkLocked(nonGroup);
 
-        verifyBeepLooped();
+        verifyBeepUnlooped();
         assertTrue(nonGroup.isInterruptive());
         assertNotEquals(-1, nonGroup.getLastAudiblyAlertedMs());
     }
@@ -878,7 +914,7 @@
 
         mService.buzzBeepBlinkLocked(group);
 
-        verifyBeepLooped();
+        verifyBeepUnlooped();
         assertTrue(group.isInterruptive());
         assertNotEquals(-1, group.getLastAudiblyAlertedMs());
     }
@@ -1293,7 +1329,11 @@
 
     @Test
     public void testListenerHintCall() throws Exception {
-        NotificationRecord r = getCallRecord(1, true);
+        NotificationChannel ringtoneChannel =
+                new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
+        ringtoneChannel.setSound(Settings.System.DEFAULT_RINGTONE_URI,
+                new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build());
+        NotificationRecord r = getCallRecord(1, ringtoneChannel, true);
 
         mService.setHints(NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS);
 
@@ -1310,7 +1350,7 @@
 
         mService.buzzBeepBlinkLocked(r);
 
-        verifyBeepLooped();
+        verifyBeepUnlooped();
     }
 
     @Test
@@ -1326,7 +1366,11 @@
 
     @Test
     public void testListenerHintBoth() throws Exception {
-        NotificationRecord r = getCallRecord(1, true);
+        NotificationChannel ringtoneChannel =
+                new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
+        ringtoneChannel.setSound(Settings.System.DEFAULT_RINGTONE_URI,
+                new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build());
+        NotificationRecord r = getCallRecord(1, ringtoneChannel, true);
         NotificationRecord s = getBeepyNotification();
 
         mService.setHints(NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS
@@ -1340,7 +1384,11 @@
 
     @Test
     public void testListenerHintNotification_callSound() throws Exception {
-        NotificationRecord r = getCallRecord(1, true);
+        NotificationChannel ringtoneChannel =
+                new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
+        ringtoneChannel.setSound(Settings.System.DEFAULT_RINGTONE_URI,
+                new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build());
+        NotificationRecord r = getCallRecord(1, ringtoneChannel, true);
 
         mService.setHints(NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS);
 
@@ -1349,6 +1397,169 @@
         verifyBeepLooped();
     }
 
+    @Test
+    public void testCannotInterruptRingtoneInsistentBeep() throws Exception {
+        NotificationChannel ringtoneChannel =
+                new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
+        ringtoneChannel.setSound(Settings.System.DEFAULT_RINGTONE_URI,
+                new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build());
+        NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true);
+        mService.addNotification(ringtoneNotification);
+
+        mService.buzzBeepBlinkLocked(ringtoneNotification);
+        verifyBeepLooped();
+
+        NotificationRecord interrupter = getBeepyOtherNotification();
+        assertTrue(mService.shouldMuteNotificationLocked(interrupter));
+        mService.buzzBeepBlinkLocked(interrupter);
+
+        verifyBeep(1);
+
+        assertFalse(interrupter.isInterruptive());
+        assertEquals(-1, interrupter.getLastAudiblyAlertedMs());
+    }
+
+    @Test
+    public void testCannotInterruptRingtoneInsistentBuzz() {
+        NotificationChannel ringtoneChannel =
+                new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
+        ringtoneChannel.setSound(Uri.EMPTY,
+                new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build());
+        ringtoneChannel.enableVibration(true);
+        NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true);
+        assertFalse(mService.shouldMuteNotificationLocked(ringtoneNotification));
+
+        mService.buzzBeepBlinkLocked(ringtoneNotification);
+        verifyVibrateLooped();
+
+        NotificationRecord interrupter = getBuzzyOtherNotification();
+        assertTrue(mService.shouldMuteNotificationLocked(interrupter));
+        mService.buzzBeepBlinkLocked(interrupter);
+
+        verifyVibrate(1);
+
+        assertFalse(interrupter.isInterruptive());
+        assertEquals(-1, interrupter.getLastAudiblyAlertedMs());
+    }
+
+    @Test
+    public void testCanInterruptRingtoneNonInsistentBeep() throws Exception {
+        NotificationChannel ringtoneChannel =
+                new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
+        ringtoneChannel.setSound(Settings.System.DEFAULT_RINGTONE_URI,
+                new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build());
+        NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, false);
+
+        mService.buzzBeepBlinkLocked(ringtoneNotification);
+        verifyBeepUnlooped();
+
+        NotificationRecord interrupter = getBeepyOtherNotification();
+        mService.buzzBeepBlinkLocked(interrupter);
+
+        verifyBeep(2);
+
+        assertTrue(interrupter.isInterruptive());
+    }
+
+    @Test
+    public void testCanInterruptRingtoneNonInsistentBuzz() {
+        NotificationChannel ringtoneChannel =
+                new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
+        ringtoneChannel.setSound(null,
+                new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build());
+        ringtoneChannel.enableVibration(true);
+        NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, false);
+
+        mService.buzzBeepBlinkLocked(ringtoneNotification);
+        verifyVibrate();
+
+        NotificationRecord interrupter = getBuzzyOtherNotification();
+        mService.buzzBeepBlinkLocked(interrupter);
+
+        verifyVibrate(2);
+
+        assertTrue(interrupter.isInterruptive());
+    }
+
+    @Test
+    public void testRingtoneInsistentBeep_doesNotBlockFutureSoundsOnceStopped() throws Exception {
+        NotificationChannel ringtoneChannel =
+                new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
+        ringtoneChannel.setSound(Settings.System.DEFAULT_RINGTONE_URI,
+                new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build());
+        NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true);
+
+        mService.buzzBeepBlinkLocked(ringtoneNotification);
+        verifyBeepLooped();
+
+        mService.clearSoundLocked();
+
+        NotificationRecord interrupter = getBeepyOtherNotification();
+        mService.buzzBeepBlinkLocked(interrupter);
+
+        verifyBeep(2);
+
+        assertTrue(interrupter.isInterruptive());
+    }
+
+    @Test
+    public void testRingtoneInsistentBuzz_doesNotBlockFutureSoundsOnceStopped() {
+        NotificationChannel ringtoneChannel =
+                new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
+        ringtoneChannel.setSound(null,
+                new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION_RINGTONE).build());
+        ringtoneChannel.enableVibration(true);
+        NotificationRecord ringtoneNotification = getCallRecord(1, ringtoneChannel, true);
+
+        mService.buzzBeepBlinkLocked(ringtoneNotification);
+        verifyVibrateLooped();
+
+        mService.clearVibrateLocked();
+
+        NotificationRecord interrupter = getBuzzyOtherNotification();
+        mService.buzzBeepBlinkLocked(interrupter);
+
+        verifyVibrate(2);
+
+        assertTrue(interrupter.isInterruptive());
+    }
+
+    @Test
+    public void testCanInterruptNonRingtoneInsistentBeep() throws Exception {
+        NotificationChannel fakeRingtoneChannel =
+                new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
+        NotificationRecord ringtoneNotification = getCallRecord(1, fakeRingtoneChannel, true);
+
+        mService.buzzBeepBlinkLocked(ringtoneNotification);
+        verifyBeepLooped();
+
+        NotificationRecord interrupter = getBeepyOtherNotification();
+        mService.buzzBeepBlinkLocked(interrupter);
+
+        verifyBeep(2);
+
+        assertTrue(interrupter.isInterruptive());
+    }
+
+    @Test
+    public void testCanInterruptNonRingtoneInsistentBuzz() {
+        NotificationChannel fakeRingtoneChannel =
+                new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
+        fakeRingtoneChannel.enableVibration(true);
+        fakeRingtoneChannel.setSound(null,
+                new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION).build());
+        NotificationRecord ringtoneNotification = getCallRecord(1, fakeRingtoneChannel, true);
+
+        mService.buzzBeepBlinkLocked(ringtoneNotification);
+
+        NotificationRecord interrupter = getBuzzyOtherNotification();
+        mService.buzzBeepBlinkLocked(interrupter);
+
+        verifyVibrate(2);
+
+        assertTrue(interrupter.isInterruptive());
+    }
+
     static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> {
         private final int mRepeatIndex;
 
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 4ea2fc0..cd0f4f1 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -537,6 +537,18 @@
         return new NotificationRecord(mContext, sbn, channel);
     }
 
+    private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
+        if (channel == null) {
+            channel = mTestNotificationChannel;
+        }
+        Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon);
+        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
+                nb.build(), new UserHandle(userId), null, 0);
+        return new NotificationRecord(mContext, sbn, channel);
+    }
+
     private Map<String, Answer> getSignalExtractorSideEffects() {
         Map<String, Answer> answers = new ArrayMap<>();
 
@@ -5451,6 +5463,112 @@
     }
 
     @Test
+    public void testGrantInlineReplyUriPermission_recordExists() throws Exception {
+        NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+                nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+        waitForIdle();
+
+        // A notification exists for the given record
+        StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
+        assertEquals(1, notifsBefore.length);
+
+        reset(mPackageManager);
+
+        Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
+
+        mService.mNotificationDelegate.grantInlineReplyUriPermission(
+                nr.getKey(), uri, nr.sbn.getUid());
+
+        // Grant permission called for the UID of SystemUI under the target user ID
+        verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
+                eq(nr.sbn.getUid()), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
+                eq(nr.sbn.getUserId()));
+    }
+
+    @Test
+    public void testGrantInlineReplyUriPermission_userAll() throws Exception {
+        // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
+        NotificationRecord nr =
+                generateNotificationRecord(mTestNotificationChannel, UserHandle.USER_ALL);
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+                nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+        waitForIdle();
+
+        // A notification exists for the given record
+        StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
+        assertEquals(1, notifsBefore.length);
+
+        reset(mPackageManager);
+
+        Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
+
+        mService.mNotificationDelegate.grantInlineReplyUriPermission(
+                nr.getKey(), uri, nr.sbn.getUid());
+
+        // Target user for the grant is USER_ALL instead of USER_SYSTEM
+        verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
+                eq(nr.sbn.getUid()), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
+                eq(UserHandle.USER_SYSTEM));
+    }
+
+    @Test
+    public void testGrantInlineReplyUriPermission_acrossUsers() throws Exception {
+        // generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
+        int otherUserId = 11;
+        NotificationRecord nr =
+                generateNotificationRecord(mTestNotificationChannel, otherUserId);
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+                nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+        waitForIdle();
+
+        // A notification exists for the given record
+        StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
+        assertEquals(1, notifsBefore.length);
+
+        reset(mPackageManager);
+
+        Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
+
+        int uid = 0; // sysui on primary user
+        int otherUserUid = (otherUserId * 100000) + 1; // SystemUI as a different user
+        String sysuiPackage = "sysui";
+        final String[] sysuiPackages = new String[] { sysuiPackage };
+        when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages);
+
+        // Make sure to mock call for USER_SYSTEM and not USER_ALL, since it's been replaced by the
+        // time this is called
+        when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId))
+                .thenReturn(otherUserUid);
+
+        mService.mNotificationDelegate.grantInlineReplyUriPermission(nr.getKey(), uri, uid);
+
+        // Target user for the grant is USER_ALL instead of USER_SYSTEM
+        verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
+                eq(otherUserUid), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
+                eq(otherUserId));
+    }
+
+    @Test
+    public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception {
+        NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
+        waitForIdle();
+
+        // No notifications exist for the given record
+        StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
+        assertEquals(0, notifsBefore.length);
+
+        Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
+        int uid = 0; // sysui on primary user
+
+        mService.mNotificationDelegate.grantInlineReplyUriPermission(nr.getKey(), uri, uid);
+
+        // Grant permission not called if no record exists for the given key
+        verify(mUgm, times(0)).grantUriPermissionFromOwner(any(), anyInt(), any(),
+                eq(uri), anyInt(), anyInt(), anyInt());
+    }
+
+    @Test
     public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
         // Bubbles are allowed!
         setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index aaaa7a5..2836e69 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -28,6 +28,7 @@
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.timeout;
@@ -128,7 +129,7 @@
 
         mActivityMetricsLogger.notifyActivityLaunching(intent);
 
-        verifyAsync(mLaunchObserver).onIntentStarted(eq(intent));
+        verifyAsync(mLaunchObserver).onIntentStarted(eq(intent), anyLong());
         verifyNoMoreInteractions(mLaunchObserver);
     }
 
@@ -163,12 +164,12 @@
        testOnActivityLaunched();
 
        mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
-               SystemClock.uptimeMillis());
+               SystemClock.elapsedRealtimeNanos());
 
        mActivityMetricsLogger.notifyWindowsDrawn(mActivityRecord.getWindowingMode(),
-               SystemClock.uptimeMillis());
+               SystemClock.elapsedRealtimeNanos());
 
-       verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mActivityRecord));
+       verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mActivityRecord), anyLong());
        verifyNoMoreInteractions(mLaunchObserver);
     }
 
@@ -186,6 +187,16 @@
     }
 
     @Test
+    public void testOnReportFullyDrawn() throws Exception {
+        testOnActivityLaunched();
+
+        mActivityMetricsLogger.logAppTransitionReportedDrawn(mActivityRecord, false);
+
+        verifyAsync(mLaunchObserver).onReportFullyDrawn(eqProto(mActivityRecord), anyLong());
+        verifyNoMoreInteractions(mLaunchObserver);
+    }
+
+    @Test
     public void testOnActivityLaunchedTrampoline() throws Exception {
         testOnIntentStarted();
 
@@ -206,12 +217,13 @@
        testOnActivityLaunchedTrampoline();
 
        mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
-               SystemClock.uptimeMillis());
+               SystemClock.elapsedRealtimeNanos());
 
        mActivityMetricsLogger.notifyWindowsDrawn(mActivityRecordTrampoline.getWindowingMode(),
-               SystemClock.uptimeMillis());
+               SystemClock.elapsedRealtimeNanos());
 
-       verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mActivityRecordTrampoline));
+       verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mActivityRecordTrampoline),
+                                                             anyLong());
        verifyNoMoreInteractions(mLaunchObserver);
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index c2a05c24..2835c1f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -891,7 +891,7 @@
         activity.app = null;
         overlayActivity.app = null;
 
-        assertEquals(2, mTask.mActivities.size());
+        assertEquals(2, mTask.getChildCount());
 
         mStack.finishDisabledPackageActivitiesLocked(activity.packageName,
                 null  /* filterByClasses */, true /* doit */, true /* evenPersistent */,
@@ -900,7 +900,7 @@
         // Although the overlay activity is in another package, the non-overlay activities are
         // removed from the task. Since the overlay activity should be removed as well, the task
         // should be empty.
-        assertThat(mTask.mActivities).isEmpty();
+        assertFalse(mTask.hasChild());
         assertThat(mStack.getAllTasks()).isEmpty();
     }
 
@@ -918,11 +918,11 @@
         // second activity will be immediately removed as it has no state.
         secondActivity.setSavedState(null /* savedState */);
 
-        assertEquals(2, mTask.mActivities.size());
+        assertEquals(2, mTask.getChildCount());
 
         mStack.handleAppDiedLocked(secondActivity.app);
 
-        assertThat(mTask.mActivities).isEmpty();
+        assertFalse(mTask.hasChild());
         assertThat(mStack.getAllTasks()).isEmpty();
     }
 
@@ -936,7 +936,7 @@
 
         mStack.handleAppDiedLocked(activity.app);
 
-        assertEquals(1, mTask.mActivities.size());
+        assertEquals(1, mTask.getChildCount());
         assertEquals(1, mStack.getAllTasks().size());
     }
 
@@ -950,7 +950,7 @@
 
         mStack.handleAppDiedLocked(activity.app);
 
-        assertThat(mTask.mActivities).isEmpty();
+        assertFalse(mTask.hasChild());
         assertThat(mStack.getAllTasks()).isEmpty();
     }
 
@@ -964,7 +964,7 @@
 
         mStack.handleAppDiedLocked(activity.app);
 
-        assertEquals(1, mTask.mActivities.size());
+        assertEquals(1, mTask.getChildCount());
         assertEquals(1, mStack.getAllTasks().size());
     }
 
@@ -978,7 +978,7 @@
 
         mStack.handleAppDiedLocked(activity.app);
 
-        assertThat(mTask.mActivities).isEmpty();
+        assertFalse(mTask.hasChild());
         assertThat(mStack.getAllTasks()).isEmpty();
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 77fbdcf..d43fe63 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -215,23 +215,6 @@
             return this;
         }
 
-        static Pair<Intent, ActivityInfo> createIntentAndActivityInfo() {
-            // TODO: Look into consolidating with dup. code in build() method below.
-            final int id = sCurrentActivityId++;
-            final ComponentName component = ComponentName.createRelative(
-                    DEFAULT_COMPONENT_PACKAGE_NAME, DEFAULT_COMPONENT_CLASS_NAME + id);
-
-            final Intent intent = new Intent();
-            intent.setComponent(component);
-
-            final ActivityInfo aInfo = new ActivityInfo();
-            aInfo.applicationInfo = new ApplicationInfo();
-            aInfo.applicationInfo.packageName = component.getPackageName();
-            aInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
-            aInfo.packageName = component.getPackageName();
-            return new Pair<>(intent, aInfo);
-        }
-
         ActivityRecord build() {
             if (mComponent == null) {
                 final int id = sCurrentActivityId++;
@@ -249,6 +232,7 @@
             intent.setComponent(mComponent);
             final ActivityInfo aInfo = new ActivityInfo();
             aInfo.applicationInfo = new ApplicationInfo();
+            aInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
             aInfo.applicationInfo.packageName = mComponent.getPackageName();
             aInfo.applicationInfo.uid = mUid;
             aInfo.packageName = mComponent.getPackageName();
diff --git a/services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
similarity index 69%
rename from services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
rename to services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
index 5cd649f..77f9f04 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
@@ -39,11 +39,11 @@
  * Tests for the {@link TaskStack} class.
  *
  * Build/Install/Run:
- *  atest FrameworksServicesTests:AnimatingAppWindowTokenRegistryTest
+ *  atest FrameworksServicesTests:AnimatingActivityRegistryTest
  */
 @SmallTest
 @Presubmit
-public class AnimatingAppWindowTokenRegistryTest extends WindowTestsBase {
+public class AnimatingActivityRegistryTest extends WindowTestsBase {
 
     @Mock
     AnimationAdapter mAdapter;
@@ -60,22 +60,22 @@
 
     @Test
     public void testDeferring() {
-        final AppWindowToken window1 = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity1 = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken window2 = createAppWindow(window1.getTask(), ACTIVITY_TYPE_STANDARD,
-                "window2").mAppToken;
-        final AnimatingAppWindowTokenRegistry registry =
-                window1.getStack().getAnimatingAppWindowTokenRegistry();
+        final ActivityRecord activity2 = createAppWindow(activity1.getTask(), ACTIVITY_TYPE_STANDARD,
+                "activity2").mActivityRecord;
+        final AnimatingActivityRegistry registry =
+                activity1.getStack().getAnimatingActivityRegistry();
 
-        window1.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
-        window2.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
-        assertTrue(window1.isSelfAnimating());
-        assertTrue(window2.isSelfAnimating());
+        activity1.startAnimation(activity1.getPendingTransaction(), mAdapter, false /* hidden */);
+        activity2.startAnimation(activity1.getPendingTransaction(), mAdapter, false /* hidden */);
+        assertTrue(activity1.isSelfAnimating());
+        assertTrue(activity2.isSelfAnimating());
 
         // Make sure that first animation finish is deferred, second one is not deferred, and first
         // one gets cancelled.
-        assertTrue(registry.notifyAboutToFinish(window1, mMockEndDeferFinishCallback1));
-        assertFalse(registry.notifyAboutToFinish(window2, mMockEndDeferFinishCallback2));
+        assertTrue(registry.notifyAboutToFinish(activity1, mMockEndDeferFinishCallback1));
+        assertFalse(registry.notifyAboutToFinish(activity2, mMockEndDeferFinishCallback2));
         verify(mMockEndDeferFinishCallback1).run();
         verifyZeroInteractions(mMockEndDeferFinishCallback2);
     }
@@ -83,12 +83,12 @@
     @Test
     @FlakyTest(bugId = 131005232)
     public void testContainerRemoved() {
-        final AppWindowToken window1 = createAppWindowToken(mDisplayContent,
+        final ActivityRecord window1 = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken window2 = createAppWindow(window1.getTask(), ACTIVITY_TYPE_STANDARD,
-                "window2").mAppToken;
-        final AnimatingAppWindowTokenRegistry registry =
-                window1.getStack().getAnimatingAppWindowTokenRegistry();
+        final ActivityRecord window2 = createAppWindow(window1.getTask(), ACTIVITY_TYPE_STANDARD,
+                "window2").mActivityRecord;
+        final AnimatingActivityRegistry registry =
+                window1.getStack().getAnimatingActivityRegistry();
 
         window1.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
         window2.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 650a911..7449efd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -57,14 +57,14 @@
 
     private TaskStack mStack;
     private Task mTask;
-    private AppWindowToken mToken;
+    private ActivityRecord mActivity;
 
     public void setUpOnDisplay(DisplayContent dc) {
         mStack = createTaskStackOnDisplay(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, dc);
         mTask = createTaskInStack(mStack, 0 /* userId */);
-        mToken = WindowTestUtils.createTestAppWindowToken(dc);
+        mActivity = WindowTestUtils.createTestActivityRecord(dc);
 
-        mTask.addChild(mToken, 0);
+        mTask.addChild(mActivity, 0);
 
         // Set a remote animator with snapshot disabled. Snapshots don't work in wmtests.
         RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
@@ -110,11 +110,11 @@
 
         // Verify we are in a change transition, but without a snapshot.
         // Though, the test will actually have crashed by now if a snapshot is attempted.
-        assertNull(mToken.getThumbnail());
-        assertTrue(mToken.isInChangeTransition());
+        assertNull(mActivity.getThumbnail());
+        assertTrue(mActivity.isInChangeTransition());
 
         waitUntilHandlersIdle();
-        mToken.removeImmediately();
+        mActivity.removeImmediately();
     }
 
     @Test
@@ -125,16 +125,16 @@
 
         mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
         assertEquals(1, mDisplayContent.mChangingApps.size());
-        assertTrue(mToken.isInChangeTransition());
+        assertTrue(mActivity.isInChangeTransition());
 
         // Removing the app-token from the display should clean-up the
         // the change leash.
-        mDisplayContent.removeAppToken(mToken.token);
+        mDisplayContent.removeAppToken(mActivity.token);
         assertEquals(0, mDisplayContent.mChangingApps.size());
-        assertFalse(mToken.isInChangeTransition());
+        assertFalse(mActivity.isInChangeTransition());
 
         waitUntilHandlersIdle();
-        mToken.removeImmediately();
+        mActivity.removeImmediately();
     }
 
     @Test
@@ -155,11 +155,11 @@
         assertEquals(WINDOWING_MODE_FULLSCREEN, mTask.getWindowingMode());
 
         // Make sure we're not waiting for a change animation (no leash)
-        assertFalse(mToken.isInChangeTransition());
-        assertNull(mToken.getThumbnail());
+        assertFalse(mActivity.isInChangeTransition());
+        assertNull(mActivity.getThumbnail());
 
         waitUntilHandlersIdle();
-        mToken.removeImmediately();
+        mActivity.removeImmediately();
     }
 
     @Test
@@ -169,14 +169,14 @@
 
         mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
         assertEquals(1, mDisplayContent.mChangingApps.size());
-        assertTrue(mToken.isInChangeTransition());
+        assertTrue(mActivity.isInChangeTransition());
 
         // Changing visibility should cancel the change transition and become closing
-        mToken.setVisibility(false, false);
+        mActivity.setVisibility(false, false);
         assertEquals(0, mDisplayContent.mChangingApps.size());
-        assertFalse(mToken.isInChangeTransition());
+        assertFalse(mActivity.isInChangeTransition());
 
         waitUntilHandlersIdle();
-        mToken.removeImmediately();
+        mActivity.removeImmediately();
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 605d520..6020453 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -57,9 +57,9 @@
     @Test
     @FlakyTest(bugId = 131005232)
     public void testTranslucentOpen() {
-        final AppWindowToken behind = createAppWindowToken(mDisplayContent,
+        final ActivityRecord behind = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken translucentOpening = createAppWindowToken(mDisplayContent,
+        final ActivityRecord translucentOpening = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         translucentOpening.setOccludesParent(false);
         translucentOpening.setHidden(true);
@@ -72,9 +72,9 @@
     @Test
     @FlakyTest(bugId = 131005232)
     public void testTranslucentClose() {
-        final AppWindowToken behind = createAppWindowToken(mDisplayContent,
+        final ActivityRecord behind = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken translucentClosing = createAppWindowToken(mDisplayContent,
+        final ActivityRecord translucentClosing = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         translucentClosing.setOccludesParent(false);
         mDisplayContent.mClosingApps.add(translucentClosing);
@@ -85,9 +85,9 @@
     @Test
     @FlakyTest(bugId = 131005232)
     public void testChangeIsNotOverwritten() {
-        final AppWindowToken behind = createAppWindowToken(mDisplayContent,
+        final ActivityRecord behind = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken translucentOpening = createAppWindowToken(mDisplayContent,
+        final ActivityRecord translucentOpening = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         translucentOpening.setOccludesParent(false);
         translucentOpening.setHidden(true);
@@ -101,10 +101,10 @@
     @Test
     @FlakyTest(bugId = 131005232)
     public void testTransitWithinTask() {
-        final AppWindowToken opening = createAppWindowToken(mDisplayContent,
+        final ActivityRecord opening = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
         opening.setOccludesParent(false);
-        final AppWindowToken closing = createAppWindowToken(mDisplayContent,
+        final ActivityRecord closing = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
         closing.setOccludesParent(false);
         final Task task = opening.getTask();
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 72d9bd0..06afce2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -122,14 +122,14 @@
         final DisplayContent dc2 = createNewDisplay(Display.STATE_ON);
 
         // Create 2 app window tokens to represent 2 activity window.
-        final AppWindowToken token1 = createTestAppWindowToken(dc1,
+        final ActivityRecord activity1 = createTestActivityRecord(dc1,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken token2 = createTestAppWindowToken(dc2,
+        final ActivityRecord activity2 = createTestActivityRecord(dc2,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
 
-        token1.allDrawn = true;
-        token1.startingDisplayed = true;
-        token1.startingMoved = true;
+        activity1.allDrawn = true;
+        activity1.startingDisplayed = true;
+        activity1.startingMoved = true;
 
         // Simulate activity resume / finish flows to prepare app transition & set visibility,
         // make sure transition is set as expected for each display.
@@ -141,8 +141,8 @@
         assertEquals(TRANSIT_ACTIVITY_CLOSE, dc2.mAppTransition.getAppTransition());
         // One activity window is visible for resuming & the other activity window is invisible
         // for finishing in different display.
-        token1.setVisibility(true, false);
-        token2.setVisibility(false, false);
+        activity1.setVisibility(true, false);
+        activity2.setVisibility(false, false);
 
         // Make sure each display is in animating stage.
         assertTrue(dc1.mOpeningApps.size() > 0);
@@ -159,12 +159,12 @@
 
         final TaskStack stack1 = createTaskStackOnDisplay(dc1);
         final Task task1 = createTaskInStack(stack1, 0 /* userId */);
-        final AppWindowToken token1 =
-                WindowTestUtils.createTestAppWindowToken(dc1);
-        task1.addChild(token1, 0);
+        final ActivityRecord activity1 =
+                WindowTestUtils.createTestActivityRecord(dc1);
+        task1.addChild(activity1, 0);
 
         // Simulate same app is during opening / closing transition set stage.
-        dc1.mClosingApps.add(token1);
+        dc1.mClosingApps.add(activity1);
         assertTrue(dc1.mClosingApps.size() > 0);
 
         dc1.prepareAppTransition(TRANSIT_ACTIVITY_OPEN,
@@ -172,15 +172,15 @@
         assertEquals(TRANSIT_ACTIVITY_OPEN, dc1.mAppTransition.getAppTransition());
         assertTrue(dc1.mAppTransition.isTransitionSet());
 
-        dc1.mOpeningApps.add(token1);
+        dc1.mOpeningApps.add(activity1);
         assertTrue(dc1.mOpeningApps.size() > 0);
 
         // Move stack to another display.
         stack1.reparent(dc2.getDisplayId(),  new Rect(), true);
 
         // Verify if token are cleared from both pending transition list in former display.
-        assertFalse(dc1.mOpeningApps.contains(token1));
-        assertFalse(dc1.mOpeningApps.contains(token1));
+        assertFalse(dc1.mOpeningApps.contains(activity1));
+        assertFalse(dc1.mOpeningApps.contains(activity1));
     }
 
     @Test
@@ -197,7 +197,7 @@
         doReturn(false).when(dc).onDescendantOrientationChanged(any(), any());
         final WindowState exitingAppWindow = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
                 dc, "exiting app");
-        final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
+        final ActivityRecord exitingActivity= exitingAppWindow.mActivityRecord;
         // Wait until everything in animation handler get executed to prevent the exiting window
         // from being removed during WindowSurfacePlacer Traversal.
         waitUntilHandlersIdle();
@@ -215,7 +215,7 @@
                 false /* alwaysKeepCurrent */, 0 /* flags */, false /* forceOverride */);
         assertEquals(TRANSIT_ACTIVITY_CLOSE, dc.mAppTransition.getAppTransition());
         dc.mAppTransition.overridePendingAppTransitionRemote(adapter);
-        exitingAppToken.setVisibility(false, false);
+        exitingActivity.setVisibility(false, false);
         assertTrue(dc.mClosingApps.size() > 0);
 
         // Make sure window is in animating stage before freeze, and cancel after freeze.
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java
index aacdeb2..8520d21 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java
@@ -47,10 +47,10 @@
     private AppWindowThumbnail buildThumbnail() {
         final GraphicBuffer buffer = GraphicBuffer.create(1, 1, PixelFormat.RGBA_8888,
                 GraphicBuffer.USAGE_SW_READ_RARELY | GraphicBuffer.USAGE_SW_WRITE_NEVER);
-        final AppWindowToken mockAwt = mock(AppWindowToken.class);
-        when(mockAwt.getPendingTransaction()).thenReturn(new StubTransaction());
-        when(mockAwt.makeSurface()).thenReturn(new MockSurfaceControlBuilder());
-        return new AppWindowThumbnail(new StubTransaction(), mockAwt,
+        final ActivityRecord mockAr = mock(ActivityRecord.class);
+        when(mockAr.getPendingTransaction()).thenReturn(new StubTransaction());
+        when(mockAr.makeSurface()).thenReturn(new MockSurfaceControlBuilder());
+        return new AppWindowThumbnail(new StubTransaction(), mockAr,
                 buffer, false, mock(Surface.class), mock(SurfaceAnimator.class));
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
index 66ba81d..b0f3b42 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
@@ -42,7 +42,7 @@
 
 
 /**
- * Animation related tests for the {@link AppWindowToken} class.
+ * Animation related tests for the {@link ActivityRecord} class.
  *
  * Build/Install/Run:
  *  atest AppWindowTokenAnimationTests
@@ -52,7 +52,7 @@
 @RunWith(WindowTestRunner.class)
 public class AppWindowTokenAnimationTests extends WindowTestsBase {
 
-    private AppWindowToken mToken;
+    private ActivityRecord mActivity;
 
     @Mock
     private AnimationAdapter mSpec;
@@ -61,39 +61,39 @@
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
-        mToken = createTestAppWindowToken(mDisplayContent, WINDOWING_MODE_FULLSCREEN,
+        mActivity = createTestActivityRecord(mDisplayContent, WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD);
     }
 
     @Test
     @FlakyTest(bugId = 131005232)
     public void clipAfterAnim_boundsLayerIsCreated() {
-        mToken.mNeedsAnimationBoundsLayer = true;
+        mActivity.mNeedsAnimationBoundsLayer = true;
 
-        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
-        verify(mTransaction).reparent(eq(mToken.getSurfaceControl()),
-                eq(mToken.mSurfaceAnimator.mLeash));
-        verify(mTransaction).reparent(eq(mToken.mSurfaceAnimator.mLeash),
-                eq(mToken.mAnimationBoundsLayer));
+        mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        verify(mTransaction).reparent(eq(mActivity.getSurfaceControl()),
+                eq(mActivity.mSurfaceAnimator.mLeash));
+        verify(mTransaction).reparent(eq(mActivity.mSurfaceAnimator.mLeash),
+                eq(mActivity.mAnimationBoundsLayer));
     }
 
     @Test
     public void clipAfterAnim_boundsLayerZBoosted() {
-        mToken.mNeedsAnimationBoundsLayer = true;
-        mToken.mNeedsZBoost = true;
+        mActivity.mNeedsAnimationBoundsLayer = true;
+        mActivity.mNeedsZBoost = true;
 
-        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
-        verify(mTransaction).setLayer(eq(mToken.mAnimationBoundsLayer),
-                intThat(layer -> layer >= AppWindowToken.Z_BOOST_BASE));
+        mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        verify(mTransaction).setLayer(eq(mActivity.mAnimationBoundsLayer),
+                intThat(layer -> layer >= ActivityRecord.Z_BOOST_BASE));
     }
 
     @Test
     @FlakyTest(bugId = 131005232)
     public void clipAfterAnim_boundsLayerIsDestroyed() {
-        mToken.mNeedsAnimationBoundsLayer = true;
-        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
-        final SurfaceControl leash = mToken.mSurfaceAnimator.mLeash;
-        final SurfaceControl animationBoundsLayer = mToken.mAnimationBoundsLayer;
+        mActivity.mNeedsAnimationBoundsLayer = true;
+        mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        final SurfaceControl leash = mActivity.mSurfaceAnimator.mLeash;
+        final SurfaceControl animationBoundsLayer = mActivity.mAnimationBoundsLayer;
         final ArgumentCaptor<SurfaceAnimator.OnAnimationFinishedCallback> callbackCaptor =
                 ArgumentCaptor.forClass(
                         SurfaceAnimator.OnAnimationFinishedCallback.class);
@@ -102,30 +102,30 @@
         callbackCaptor.getValue().onAnimationFinished(mSpec);
         verify(mTransaction).remove(eq(leash));
         verify(mTransaction).remove(eq(animationBoundsLayer));
-        assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse();
+        assertThat(mActivity.mNeedsAnimationBoundsLayer).isFalse();
     }
 
     @Test
     public void clipAfterAnimCancelled_boundsLayerIsDestroyed() {
-        mToken.mNeedsAnimationBoundsLayer = true;
-        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
-        final SurfaceControl leash = mToken.mSurfaceAnimator.mLeash;
-        final SurfaceControl animationBoundsLayer = mToken.mAnimationBoundsLayer;
+        mActivity.mNeedsAnimationBoundsLayer = true;
+        mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        final SurfaceControl leash = mActivity.mSurfaceAnimator.mLeash;
+        final SurfaceControl animationBoundsLayer = mActivity.mAnimationBoundsLayer;
 
-        mToken.mSurfaceAnimator.cancelAnimation();
+        mActivity.mSurfaceAnimator.cancelAnimation();
         verify(mTransaction).remove(eq(leash));
         verify(mTransaction).remove(eq(animationBoundsLayer));
-        assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse();
+        assertThat(mActivity.mNeedsAnimationBoundsLayer).isFalse();
     }
 
     @Test
     @FlakyTest(bugId = 131005232)
     public void clipNoneAnim_boundsLayerIsNotCreated() {
-        mToken.mNeedsAnimationBoundsLayer = false;
+        mActivity.mNeedsAnimationBoundsLayer = false;
 
-        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
-        verify(mTransaction).reparent(eq(mToken.getSurfaceControl()),
-                eq(mToken.mSurfaceAnimator.mLeash));
-        assertThat(mToken.mAnimationBoundsLayer).isNull();
+        mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        verify(mTransaction).reparent(eq(mActivity.getSurfaceControl()),
+                eq(mActivity.mSurfaceAnimator.mLeash));
+        assertThat(mActivity.mAnimationBoundsLayer).isNull();
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 2661735..d68aef0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -65,7 +65,7 @@
 import org.mockito.Mockito;
 
 /**
- * Tests for the {@link AppWindowToken} class.
+ * Tests for the {@link ActivityRecord} class.
  *
  * Build/Install/Run:
  *  atest WmTests:AppWindowTokenTests
@@ -77,7 +77,7 @@
 
     TaskStack mStack;
     Task mTask;
-    AppWindowToken mToken;
+    ActivityRecord mActivity;
 
     private final String mPackageName = getInstrumentation().getTargetContext().getPackageName();
 
@@ -85,68 +85,68 @@
     public void setUp() throws Exception {
         mStack = createTaskStackOnDisplay(mDisplayContent);
         mTask = createTaskInStack(mStack, 0 /* userId */);
-        mToken = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
+        mActivity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
 
-        mTask.addChild(mToken, 0);
+        mTask.addChild(mActivity, 0);
     }
 
     @Test
     @Presubmit
     public void testAddWindow_Order() {
-        assertEquals(0, mToken.getChildCount());
+        assertEquals(0, mActivity.getChildCount());
 
-        final WindowState win1 = createWindow(null, TYPE_APPLICATION, mToken, "win1");
-        final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, mToken,
+        final WindowState win1 = createWindow(null, TYPE_APPLICATION, mActivity, "win1");
+        final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, mActivity,
                 "startingWin");
-        final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, mToken, "baseWin");
-        final WindowState win4 = createWindow(null, TYPE_APPLICATION, mToken, "win4");
+        final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, mActivity, "baseWin");
+        final WindowState win4 = createWindow(null, TYPE_APPLICATION, mActivity, "win4");
 
         // Should not contain the windows that were added above.
-        assertEquals(4, mToken.getChildCount());
-        assertTrue(mToken.mChildren.contains(win1));
-        assertTrue(mToken.mChildren.contains(startingWin));
-        assertTrue(mToken.mChildren.contains(baseWin));
-        assertTrue(mToken.mChildren.contains(win4));
+        assertEquals(4, mActivity.getChildCount());
+        assertTrue(mActivity.mChildren.contains(win1));
+        assertTrue(mActivity.mChildren.contains(startingWin));
+        assertTrue(mActivity.mChildren.contains(baseWin));
+        assertTrue(mActivity.mChildren.contains(win4));
 
         // The starting window should be on-top of all other windows.
-        assertEquals(startingWin, mToken.mChildren.peekLast());
+        assertEquals(startingWin, mActivity.mChildren.peekLast());
 
         // The base application window should be below all other windows.
-        assertEquals(baseWin, mToken.mChildren.peekFirst());
-        mToken.removeImmediately();
+        assertEquals(baseWin, mActivity.mChildren.peekFirst());
+        mActivity.removeImmediately();
     }
 
     @Test
     @Presubmit
     public void testFindMainWindow() {
-        assertNull(mToken.findMainWindow());
+        assertNull(mActivity.findMainWindow());
 
-        final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, mToken, "window1");
-        final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, mToken, "window11");
-        final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, mToken, "window12");
-        assertEquals(window1, mToken.findMainWindow());
+        final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, mActivity, "window1");
+        final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, mActivity, "window11");
+        final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, mActivity, "window12");
+        assertEquals(window1, mActivity.findMainWindow());
         window1.mAnimatingExit = true;
-        assertEquals(window1, mToken.findMainWindow());
-        final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, mToken,
+        assertEquals(window1, mActivity.findMainWindow());
+        final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, mActivity,
                 "window2");
-        assertEquals(window2, mToken.findMainWindow());
-        mToken.removeImmediately();
+        assertEquals(window2, mActivity.findMainWindow());
+        mActivity.removeImmediately();
     }
 
     @Test
     @Presubmit
     public void testGetTopFullscreenWindow() {
-        assertNull(mToken.getTopFullscreenWindow());
+        assertNull(mActivity.getTopFullscreenWindow());
 
-        final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, mToken, "window1");
-        final WindowState window11 = createWindow(null, TYPE_APPLICATION, mToken, "window11");
-        final WindowState window12 = createWindow(null, TYPE_APPLICATION, mToken, "window12");
-        assertEquals(window12, mToken.getTopFullscreenWindow());
+        final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, mActivity, "window1");
+        final WindowState window11 = createWindow(null, TYPE_APPLICATION, mActivity, "window11");
+        final WindowState window12 = createWindow(null, TYPE_APPLICATION, mActivity, "window12");
+        assertEquals(window12, mActivity.getTopFullscreenWindow());
         window12.mAttrs.width = 500;
-        assertEquals(window11, mToken.getTopFullscreenWindow());
+        assertEquals(window11, mActivity.getTopFullscreenWindow());
         window11.mAttrs.width = 500;
-        assertEquals(window1, mToken.getTopFullscreenWindow());
-        mToken.removeImmediately();
+        assertEquals(window1, mActivity.getTopFullscreenWindow());
+        mActivity.removeImmediately();
     }
 
     @Test
@@ -155,11 +155,11 @@
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
                 TYPE_BASE_APPLICATION);
         attrs.setTitle("AppWindow");
-        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mToken);
-        mToken.addWindow(appWindow);
+        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mActivity);
+        mActivity.addWindow(appWindow);
 
         // Set initial orientation and update.
-        mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        mActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
         mDisplayContent.updateOrientation(
                 mDisplayContent.getRequestedOverrideConfiguration(),
                 null /* freezeThisOneIfNeeded */, false /* forceUpdate */);
@@ -167,7 +167,7 @@
         appWindow.mResizeReported = false;
 
         // Update the orientation to perform 180 degree rotation and check that resize was reported.
-        mToken.setOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
+        mActivity.setOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
         mDisplayContent.updateOrientation(
                 mDisplayContent.getRequestedOverrideConfiguration(),
                 null /* freezeThisOneIfNeeded */, false /* forceUpdate */);
@@ -187,8 +187,8 @@
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
                 TYPE_BASE_APPLICATION);
         attrs.setTitle("RotationByPolicy");
-        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mToken);
-        mToken.addWindow(appWindow);
+        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mActivity);
+        mActivity.addWindow(appWindow);
 
         // Set initial orientation and update.
         performRotation(displayRotation, Surface.ROTATION_90);
@@ -208,10 +208,10 @@
 
     @Test
     public void testSizeCompatBounds() {
-        final Rect fixedBounds = mToken.getRequestedOverrideConfiguration().windowConfiguration
+        final Rect fixedBounds = mActivity.getRequestedOverrideConfiguration().windowConfiguration
                 .getBounds();
         fixedBounds.set(0, 0, 1200, 1600);
-        mToken.getRequestedOverrideConfiguration().windowConfiguration.setAppBounds(fixedBounds);
+        mActivity.getRequestedOverrideConfiguration().windowConfiguration.setAppBounds(fixedBounds);
         final Configuration newParentConfig = mTask.getConfiguration();
 
         // Change the size of the container to two times smaller with insets.
@@ -219,50 +219,50 @@
         final Rect containerAppBounds = newParentConfig.windowConfiguration.getAppBounds();
         final Rect containerBounds = newParentConfig.windowConfiguration.getBounds();
         containerBounds.set(0, 0, 600, 800);
-        mToken.onConfigurationChanged(newParentConfig);
+        mActivity.onConfigurationChanged(newParentConfig);
 
-        assertTrue(mToken.hasSizeCompatBounds());
-        assertEquals(containerAppBounds, mToken.getBounds());
+        assertTrue(mActivity.hasSizeCompatBounds());
+        assertEquals(containerAppBounds, mActivity.getBounds());
         assertEquals((float) containerAppBounds.width() / fixedBounds.width(),
-                mToken.getSizeCompatScale(), 0.0001f /* delta */);
+                mActivity.getSizeCompatScale(), 0.0001f /* delta */);
 
         // Change the width of the container to two times bigger.
         containerAppBounds.set(0, 0, 2400, 1600);
         containerBounds.set(containerAppBounds);
-        mToken.onConfigurationChanged(newParentConfig);
+        mActivity.onConfigurationChanged(newParentConfig);
 
-        assertTrue(mToken.hasSizeCompatBounds());
+        assertTrue(mActivity.hasSizeCompatBounds());
         // Don't scale up, so the bounds keep the same as the fixed width.
-        assertEquals(fixedBounds.width(), mToken.getBounds().width());
+        assertEquals(fixedBounds.width(), mActivity.getBounds().width());
         // Assert the position is horizontal center.
         assertEquals((containerAppBounds.width() - fixedBounds.width()) / 2,
-                mToken.getBounds().left);
-        assertEquals(1f, mToken.getSizeCompatScale(), 0.0001f  /* delta */);
+                mActivity.getBounds().left);
+        assertEquals(1f, mActivity.getSizeCompatScale(), 0.0001f  /* delta */);
 
         // Change the width of the container to fit the fixed bounds.
         containerBounds.set(0, 0, 1200, 2000);
-        mToken.onConfigurationChanged(newParentConfig);
+        mActivity.onConfigurationChanged(newParentConfig);
         // Assert don't use fixed bounds because the region is enough.
-        assertFalse(mToken.hasSizeCompatBounds());
+        assertFalse(mActivity.hasSizeCompatBounds());
     }
 
     @Test
     @Presubmit
     public void testGetOrientation() {
-        mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        mActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
-        mToken.setOccludesParent(false);
+        mActivity.setOccludesParent(false);
         // Can specify orientation if app doesn't occludes parent.
-        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mToken.getOrientation());
+        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mActivity.getOrientation());
 
-        mToken.setOccludesParent(true);
-        mToken.setHidden(true);
-        mToken.sendingToBottom = true;
+        mActivity.setOccludesParent(true);
+        mActivity.setHidden(true);
+        mActivity.sendingToBottom = true;
         // Can not specify orientation if app isn't visible even though it occludes parent.
-        assertEquals(SCREEN_ORIENTATION_UNSET, mToken.getOrientation());
+        assertEquals(SCREEN_ORIENTATION_UNSET, mActivity.getOrientation());
         // Can specify orientation if the current orientation candidate is orientation behind.
         assertEquals(SCREEN_ORIENTATION_LANDSCAPE,
-                mToken.getOrientation(SCREEN_ORIENTATION_BEHIND));
+                mActivity.getOrientation(SCREEN_ORIENTATION_BEHIND));
     }
 
     @Test
@@ -272,24 +272,24 @@
                 TYPE_BASE_APPLICATION);
         attrs.flags |= FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD;
         attrs.setTitle("AppWindow");
-        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mToken);
+        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mActivity);
 
         // Add window with show when locked flag
-        mToken.addWindow(appWindow);
-        assertTrue(mToken.containsShowWhenLockedWindow() && mToken.containsDismissKeyguardWindow());
+        mActivity.addWindow(appWindow);
+        assertTrue(mActivity.containsShowWhenLockedWindow() && mActivity.containsDismissKeyguardWindow());
 
         // Start relaunching
-        mToken.startRelaunching();
-        assertTrue(mToken.containsShowWhenLockedWindow() && mToken.containsDismissKeyguardWindow());
+        mActivity.startRelaunching();
+        assertTrue(mActivity.containsShowWhenLockedWindow() && mActivity.containsDismissKeyguardWindow());
 
         // Remove window and make sure that we still report back flag
-        mToken.removeChild(appWindow);
-        assertTrue(mToken.containsShowWhenLockedWindow() && mToken.containsDismissKeyguardWindow());
+        mActivity.removeChild(appWindow);
+        assertTrue(mActivity.containsShowWhenLockedWindow() && mActivity.containsDismissKeyguardWindow());
 
         // Finish relaunching and ensure flag is now not reported
-        mToken.finishRelaunching();
+        mActivity.finishRelaunching();
         assertFalse(
-                mToken.containsShowWhenLockedWindow() || mToken.containsDismissKeyguardWindow());
+                mActivity.containsShowWhenLockedWindow() || mActivity.containsDismissKeyguardWindow());
     }
 
     @Test
@@ -298,11 +298,11 @@
                 "closingWindow");
         closingWindow.mAnimatingExit = true;
         closingWindow.mRemoveOnExit = true;
-        closingWindow.mAppToken.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
+        closingWindow.mActivityRecord.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
                 true /* performLayout */, false /* isVoiceInteraction */);
 
         // We pretended that we were running an exit animation, but that should have been cleared up
-        // by changing visibility of AppWindowToken
+        // by changing visibility of ActivityRecord
         closingWindow.removeIfPossible();
         assertTrue(closingWindow.mRemoved);
     }
@@ -310,14 +310,14 @@
     @Test
     public void testSetOrientation() {
         // Assert orientation is unspecified to start.
-        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, mToken.getOrientation());
+        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, mActivity.getOrientation());
 
-        mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
-        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mToken.getOrientation());
+        mActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mActivity.getOrientation());
 
-        mDisplayContent.removeAppToken(mToken.token);
+        mDisplayContent.removeAppToken(mActivity.token);
         // Assert orientation is unset to after container is removed.
-        assertEquals(SCREEN_ORIENTATION_UNSET, mToken.getOrientation());
+        assertEquals(SCREEN_ORIENTATION_UNSET, mActivity.getOrientation());
 
         // Reset display frozen state
         mWm.mDisplayFrozen = false;
@@ -325,13 +325,13 @@
 
     @Test
     public void testReportOrientationChange() {
-        mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        mActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         mDisplayContent.getDisplayRotation().setFixedToUserRotation(
                 DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
 
         mTask.mTaskRecord = Mockito.mock(TaskRecord.class, RETURNS_DEEP_STUBS);
-        mToken.reportDescendantOrientationChangeIfNeeded();
+        mActivity.reportDescendantOrientationChangeIfNeeded();
 
         verify(mTask.mTaskRecord).onConfigurationChanged(any(Configuration.class));
     }
@@ -339,14 +339,14 @@
     @Test
     @FlakyTest(bugId = 131176283)
     public void testCreateRemoveStartingWindow() {
-        mToken.addStartingWindow(mPackageName,
+        mActivity.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                 false, false);
         waitUntilHandlersIdle();
-        assertHasStartingWindow(mToken);
-        mToken.removeStartingWindow();
+        assertHasStartingWindow(mActivity);
+        mActivity.removeStartingWindow();
         waitUntilHandlersIdle();
-        assertNoStartingWindow(mToken);
+        assertNoStartingWindow(mActivity);
     }
 
     @Test
@@ -354,7 +354,7 @@
     public void testAddRemoveRace() {
         // There was once a race condition between adding and removing starting windows
         for (int i = 0; i < 1000; i++) {
-            final AppWindowToken appToken = createIsolatedTestAppWindowToken();
+            final ActivityRecord appToken = createIsolatedTestActivityRecord();
 
             appToken.addStartingWindow(mPackageName,
                     android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
@@ -369,76 +369,76 @@
 
     @Test
     public void testTransferStartingWindow() {
-        final AppWindowToken token1 = createIsolatedTestAppWindowToken();
-        final AppWindowToken token2 = createIsolatedTestAppWindowToken();
-        token1.addStartingWindow(mPackageName,
+        final ActivityRecord activity1 = createIsolatedTestActivityRecord();
+        final ActivityRecord activity2 = createIsolatedTestActivityRecord();
+        activity1.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                 false, false);
         waitUntilHandlersIdle();
-        token2.addStartingWindow(mPackageName,
-                android.R.style.Theme, null, "Test", 0, 0, 0, 0, token1.appToken.asBinder(),
+        activity2.addStartingWindow(mPackageName,
+                android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity1.appToken.asBinder(),
                 true, true, false, true, false, false);
         waitUntilHandlersIdle();
-        assertNoStartingWindow(token1);
-        assertHasStartingWindow(token2);
+        assertNoStartingWindow(activity1);
+        assertHasStartingWindow(activity2);
     }
 
     @Test
     public void testTransferStartingWindowWhileCreating() {
-        final AppWindowToken token1 = createIsolatedTestAppWindowToken();
-        final AppWindowToken token2 = createIsolatedTestAppWindowToken();
-        ((TestWindowManagerPolicy) token1.mWmService.mPolicy).setRunnableWhenAddingSplashScreen(
+        final ActivityRecord activity1 = createIsolatedTestActivityRecord();
+        final ActivityRecord activity2 = createIsolatedTestActivityRecord();
+        ((TestWindowManagerPolicy) activity1.mWmService.mPolicy).setRunnableWhenAddingSplashScreen(
                 () -> {
                     // Surprise, ...! Transfer window in the middle of the creation flow.
-                    token2.addStartingWindow(mPackageName,
+                    activity2.addStartingWindow(mPackageName,
                             android.R.style.Theme, null, "Test", 0, 0, 0, 0,
-                            token1.appToken.asBinder(), true, true, false,
+                            activity1.appToken.asBinder(), true, true, false,
                             true, false, false);
                 });
-        token1.addStartingWindow(mPackageName,
+        activity1.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                 false, false);
         waitUntilHandlersIdle();
-        assertNoStartingWindow(token1);
-        assertHasStartingWindow(token2);
+        assertNoStartingWindow(activity1);
+        assertHasStartingWindow(activity2);
     }
 
-    private AppWindowToken createIsolatedTestAppWindowToken() {
+    private ActivityRecord createIsolatedTestActivityRecord() {
         final TaskStack taskStack = createTaskStackOnDisplay(mDisplayContent);
         final Task task = createTaskInStack(taskStack, 0 /* userId */);
-        return createTestAppWindowTokenForGivenTask(task);
+        return createTestActivityRecordForGivenTask(task);
     }
 
-    private AppWindowToken createTestAppWindowTokenForGivenTask(Task task) {
-        final AppWindowToken appToken =
-                WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        task.addChild(appToken, 0);
+    private ActivityRecord createTestActivityRecordForGivenTask(Task task) {
+        final ActivityRecord activity =
+                WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        task.addChild(activity, 0);
         waitUntilHandlersIdle();
-        return appToken;
+        return activity;
     }
 
     @Test
     public void testTryTransferStartingWindowFromHiddenAboveToken() {
         // Add two tasks on top of each other.
-        final AppWindowToken tokenTop = createIsolatedTestAppWindowToken();
-        final AppWindowToken tokenBottom =
-                createTestAppWindowTokenForGivenTask(tokenTop.getTask());
+        final ActivityRecord activityTop = createIsolatedTestActivityRecord();
+        final ActivityRecord activityBottom =
+                createTestActivityRecordForGivenTask(activityTop.getTask());
 
         // Add a starting window.
-        tokenTop.addStartingWindow(mPackageName,
+        activityTop.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                 false, false);
         waitUntilHandlersIdle();
 
         // Make the top one invisible, and try transferring the starting window from the top to the
         // bottom one.
-        tokenTop.setVisibility(false, false);
-        tokenBottom.transferStartingWindowFromHiddenAboveTokenIfNeeded();
+        activityTop.setVisibility(false, false);
+        activityBottom.transferStartingWindowFromHiddenAboveTokenIfNeeded();
         waitUntilHandlersIdle();
 
         // Assert that the bottom window now has the starting window.
-        assertNoStartingWindow(tokenTop);
-        assertHasStartingWindow(tokenBottom);
+        assertNoStartingWindow(activityTop);
+        assertHasStartingWindow(activityBottom);
     }
 
     @Test
@@ -450,40 +450,40 @@
 
         // Check that anim bounds for freeform window match task bounds
         mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
-        assertEquals(taskBounds, mToken.getAnimationBounds(STACK_CLIP_NONE));
+        assertEquals(taskBounds, mActivity.getAnimationBounds(STACK_CLIP_NONE));
 
         // STACK_CLIP_AFTER_ANIM should use task bounds since they will be clipped by
         // bounds animation layer.
         mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        assertEquals(taskBounds, mToken.getAnimationBounds(STACK_CLIP_AFTER_ANIM));
+        assertEquals(taskBounds, mActivity.getAnimationBounds(STACK_CLIP_AFTER_ANIM));
 
         // STACK_CLIP_BEFORE_ANIM should use stack bounds since it won't be clipped later.
         mTask.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
-        assertEquals(stackBounds, mToken.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
+        assertEquals(stackBounds, mActivity.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
     }
 
     @Test
     public void testHasStartingWindow() {
         final WindowManager.LayoutParams attrs =
                 new WindowManager.LayoutParams(TYPE_APPLICATION_STARTING);
-        final WindowTestUtils.TestWindowState startingWindow = createWindowState(attrs, mToken);
-        mToken.startingDisplayed = true;
-        mToken.addWindow(startingWindow);
-        assertTrue("Starting window should be present", mToken.hasStartingWindow());
-        mToken.startingDisplayed = false;
-        assertTrue("Starting window should be present", mToken.hasStartingWindow());
+        final WindowTestUtils.TestWindowState startingWindow = createWindowState(attrs, mActivity);
+        mActivity.startingDisplayed = true;
+        mActivity.addWindow(startingWindow);
+        assertTrue("Starting window should be present", mActivity.hasStartingWindow());
+        mActivity.startingDisplayed = false;
+        assertTrue("Starting window should be present", mActivity.hasStartingWindow());
 
-        mToken.removeChild(startingWindow);
-        assertFalse("Starting window should not be present", mToken.hasStartingWindow());
+        mActivity.removeChild(startingWindow);
+        assertFalse("Starting window should not be present", mActivity.hasStartingWindow());
     }
 
-    private void assertHasStartingWindow(AppWindowToken atoken) {
+    private void assertHasStartingWindow(ActivityRecord atoken) {
         assertNotNull(atoken.startingSurface);
         assertNotNull(atoken.mStartingData);
         assertNotNull(atoken.startingWindow);
     }
 
-    private void assertNoStartingWindow(AppWindowToken atoken) {
+    private void assertNoStartingWindow(ActivityRecord atoken) {
         assertNull(atoken.startingSurface);
         assertNull(atoken.startingWindow);
         assertNull(atoken.mStartingData);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 2ba3cbd..01489c6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -113,13 +113,13 @@
     public void testForAllWindows() {
         final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
                 mDisplayContent, "exiting app");
-        final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
+        final ActivityRecord exitingApp = exitingAppWindow.mActivityRecord;
         // Wait until everything in animation handler get executed to prevent the exiting window
         // from being removed during WindowSurfacePlacer Traversal.
         waitUntilHandlersIdle();
 
-        exitingAppToken.mIsExiting = true;
-        exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
+        exitingApp.mIsExiting = true;
+        exitingApp.getTask().mStack.mExitingActivities.add(exitingApp);
 
         assertForAllWindowsOrder(Arrays.asList(
                 mWallpaperWindow,
@@ -241,10 +241,10 @@
         assertEquals(dc, stack.getDisplayContent());
 
         final Task task = createTaskInStack(stack, 0 /* userId */);
-        final AppWindowToken token = WindowTestUtils.createTestAppWindowToken(dc);
-        task.addChild(token, 0);
+        final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(dc);
+        task.addChild(activity, 0);
         assertEquals(dc, task.getDisplayContent());
-        assertEquals(dc, token.getDisplayContent());
+        assertEquals(dc, activity.getDisplayContent());
 
         // Move stack to first display.
         mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
@@ -252,7 +252,7 @@
         assertEquals(mDisplayContent, stack.getParent().getParent());
         assertEquals(mDisplayContent, stack.getDisplayContent());
         assertEquals(mDisplayContent, task.getDisplayContent());
-        assertEquals(mDisplayContent, token.getDisplayContent());
+        assertEquals(mDisplayContent, activity.getDisplayContent());
     }
 
     /**
@@ -313,17 +313,17 @@
         // Add stack with activity.
         final TaskStack stack0 = createTaskStackOnDisplay(dc0);
         final Task task0 = createTaskInStack(stack0, 0 /* userId */);
-        final AppWindowToken token =
-                WindowTestUtils.createTestAppWindowToken(dc0);
-        task0.addChild(token, 0);
+        final ActivityRecord activity =
+                WindowTestUtils.createTestActivityRecord(dc0);
+        task0.addChild(activity, 0);
         dc0.configureDisplayPolicy();
         assertNotNull(dc0.mTapDetector);
 
         final TaskStack stack1 = createTaskStackOnDisplay(dc1);
         final Task task1 = createTaskInStack(stack1, 0 /* userId */);
-        final AppWindowToken token1 =
-                WindowTestUtils.createTestAppWindowToken(dc0);
-        task1.addChild(token1, 0);
+        final ActivityRecord activity1 =
+                WindowTestUtils.createTestActivityRecord(dc0);
+        task1.addChild(activity1, 0);
         dc1.configureDisplayPolicy();
         assertNotNull(dc1.mTapDetector);
 
@@ -362,7 +362,7 @@
         // Create a focusable window and check that focus is calculated correctly
         final WindowState window1 =
                 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
-        window1.mAppToken.mTargetSdk = targetSdk;
+        window1.mActivityRecord.mTargetSdk = targetSdk;
         updateFocusedWindow();
         assertTrue(window1.isFocused());
         assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
@@ -375,7 +375,7 @@
 
         // Add a window to the second display, and it should be focused
         final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
-        window2.mAppToken.mTargetSdk = targetSdk;
+        window2.mActivityRecord.mTargetSdk = targetSdk;
         updateFocusedWindow();
         assertTrue(window2.isFocused());
         assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
@@ -389,8 +389,8 @@
         assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
 
         // Make sure top focused display not changed if there is a focused app.
-        window1.mAppToken.hiddenRequested = true;
-        window1.getDisplayContent().setFocusedApp(window1.mAppToken);
+        window1.mActivityRecord.hiddenRequested = true;
+        window1.getDisplayContent().setFocusedApp(window1.mActivityRecord);
         updateFocusedWindow();
         assertTrue(!window1.isFocused());
         assertEquals(window1.getDisplayId(),
@@ -569,7 +569,7 @@
         // Create a window that requests landscape orientation. It will define device orientation
         // by default.
         final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
-        window.mAppToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        window.mActivityRecord.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
         keyguard.mHasSurface = true;
@@ -682,16 +682,15 @@
         // is appWin & null on the other display.
         mDisplayContent.setInputMethodWindowLocked(mImeWindow);
         newDisplay.setInputMethodWindowLocked(null);
-        assertTrue("appWin should be IME target window",
-                appWin.equals(mDisplayContent.mInputMethodTarget));
+        assertEquals("appWin should be IME target window",
+                appWin, mDisplayContent.mInputMethodTarget);
         assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
 
         // Switch input method window on new display & make sure the input method target also
         // switched as expected.
         newDisplay.setInputMethodWindowLocked(mImeWindow);
         mDisplayContent.setInputMethodWindowLocked(null);
-        assertTrue("appWin1 should be IME target window",
-                appWin1.equals(newDisplay.mInputMethodTarget));
+        assertEquals("appWin1 should be IME target window", appWin1, newDisplay.mInputMethodTarget);
         assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
     }
 
@@ -748,7 +747,7 @@
                      new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
             final DisplayContent dc = createNewDisplay();
             dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
-            assertEquals(dc.mInputMethodTarget.mAppToken.getSurfaceControl(),
+            assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
                     dc.computeImeParent());
         }
     }
@@ -767,8 +766,8 @@
 
     @Test
     public void testComputeImeParent_app_notMatchParentBounds() {
-        spyOn(mAppWindow.mAppToken);
-        doReturn(false).when(mAppWindow.mAppToken).matchParentBounds();
+        spyOn(mAppWindow.mActivityRecord);
+        doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
         mDisplayContent.mInputMethodTarget = mAppWindow;
         // The surface parent of IME should be the display instead of app window.
         assertEquals(mDisplayContent.getWindowingLayer(), mDisplayContent.computeImeParent());
@@ -882,7 +881,7 @@
         win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility =
                 SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION
                         | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
-        win.mAppToken.mTargetSdk = P;
+        win.mActivityRecord.mTargetSdk = P;
 
         dc.setLayoutNeeded();
         dc.performLayout(true /* initial */, false /* updateImeWindows */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 480c468..bb4d35f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -638,7 +638,7 @@
         mBuilder.build();
 
         final WindowState win = mock(WindowState.class);
-        win.mAppToken = mock(AppWindowToken.class);
+        win.mActivityRecord = mock(ActivityRecord.class);
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams();
         attrs.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
 
@@ -648,13 +648,13 @@
         mMockDisplayContent.mCurrentFocus = win;
         mTarget.mUpsideDownRotation = Surface.ROTATION_180;
 
-        doReturn(true).when(win.mAppToken).matchParentBounds();
+        doReturn(true).when(win.mActivityRecord).matchParentBounds();
         // The focused fullscreen opaque window without override bounds should be able to be
         // rotated seamlessly.
         assertTrue(mTarget.shouldRotateSeamlessly(
                 Surface.ROTATION_0, Surface.ROTATION_90, false /* forceUpdate */));
 
-        doReturn(false).when(win.mAppToken).matchParentBounds();
+        doReturn(false).when(win.mActivityRecord).matchParentBounds();
         // No seamless rotation if the window may be positioned with offset after rotation.
         assertFalse(mTarget.shouldRotateSeamlessly(
                 Surface.ROTATION_0, Surface.ROTATION_90, false /* forceUpdate */));
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index 304df22..bfb4607 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -96,15 +96,15 @@
      * Creates a window state which can be used as a drop target.
      */
     private WindowState createDropTargetWindow(String name, int ownerId) {
-        final AppWindowToken token = WindowTestUtils.createTestAppWindowToken(
+        final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(
                 mDisplayContent);
         final TaskStack stack = createTaskStackOnDisplay(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
         final Task task = createTaskInStack(stack, ownerId);
-        task.addChild(token, 0);
+        task.addChild(activity, 0);
 
         final WindowState window = createWindow(
-                null, TYPE_BASE_APPLICATION, token, name, ownerId, false);
+                null, TYPE_BASE_APPLICATION, activity, name, ownerId, false);
         window.mInputChannel = new InputChannel();
         window.mHasSurface = true;
         return window;
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index f353846..fff77f5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -99,14 +99,14 @@
 
     @Test
     public void testRemovedBeforeStarted_expectCanceled() throws Exception {
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        AnimationAdapter adapter = mController.addAnimation(appWindow.getTask(),
+        AnimationAdapter adapter = mController.addAnimation(activity.getTask(),
                 false /* isRecentTaskInvisible */);
         adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
 
         // Remove the app window so that the animation target can not be created
-        appWindow.removeImmediately();
+        activity.removeImmediately();
         mController.startAnimation();
 
         // Verify that the finish callback to reparent the leash is called
@@ -118,14 +118,14 @@
 
     @Test
     public void testCancelAfterRemove_expectIgnored() {
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        AnimationAdapter adapter = mController.addAnimation(appWindow.getTask(),
+        AnimationAdapter adapter = mController.addAnimation(activity.getTask(),
                 false /* isRecentTaskInvisible */);
         adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
 
         // Remove the app window so that the animation target can not be created
-        appWindow.removeImmediately();
+        activity.removeImmediately();
         mController.startAnimation();
         mController.cleanupAnimation(REORDER_KEEP_IN_PLACE);
         try {
@@ -140,24 +140,24 @@
         mWm.setRecentsAnimationController(mController);
         final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
-        final AppWindowToken homeAppWindow =
+        final ActivityRecord homeActivity =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                         .setStack(homeStack)
                         .setCreateTask(true)
                         .build();
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken hiddenAppWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord hiddenActivity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        hiddenAppWindow.setHidden(true);
+        hiddenActivity.setHidden(true);
         mDisplayContent.getConfiguration().windowConfiguration.setRotation(
                 mDisplayContent.getRotation());
         mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray());
 
         // Ensure that we are animating the target activity as well
-        assertTrue(mController.isAnimatingTask(homeAppWindow.getTask()));
-        assertTrue(mController.isAnimatingTask(appWindow.getTask()));
-        assertFalse(mController.isAnimatingTask(hiddenAppWindow.getTask()));
+        assertTrue(mController.isAnimatingTask(homeActivity.getTask()));
+        assertTrue(mController.isAnimatingTask(activity.getTask()));
+        assertFalse(mController.isAnimatingTask(hiddenActivity.getTask()));
     }
 
     @Test
@@ -165,12 +165,12 @@
         mWm.setRecentsAnimationController(mController);
         final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
-        final AppWindowToken homeAppWindow =
+        final ActivityRecord homeAppWindow =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                         .setStack(homeStack)
                         .setCreateTask(true)
                         .build();
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord appWindow = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
         appWindow.addWindow(win1);
@@ -194,15 +194,15 @@
         mWm.setRecentsAnimationController(mController);
         final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
-        final AppWindowToken homeAppWindow =
+        final ActivityRecord homeActivity =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                         .setStack(homeStack)
                         .setCreateTask(true)
                         .build();
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
-        appWindow.addWindow(win1);
+        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
+        activity.addWindow(win1);
         final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
                 mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */);
         spyOn(mDisplayContent.mWallpaperController);
@@ -215,7 +215,7 @@
 
         // Cancel the animation and ensure the controller is still running
         wallpaperWindowToken.cancelAnimation();
-        assertTrue(mController.isAnimatingTask(appWindow.getTask()));
+        assertTrue(mController.isAnimatingTask(activity.getTask()));
         assertFalse(mController.isAnimatingWallpaper(wallpaperWindowToken));
         verify(mMockRunner, never()).onAnimationCanceled(null /* taskSnapshot */);
     }
@@ -225,17 +225,17 @@
         mWm.setRecentsAnimationController(mController);
         final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
-        final AppWindowToken homeAppWindow =
+        final ActivityRecord homeActivity =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                         .setStack(homeStack)
                         .setCreateTask(true)
                         .build();
-        final WindowState hwin1 = createWindow(null, TYPE_BASE_APPLICATION, homeAppWindow, "hwin1");
-        homeAppWindow.addWindow(hwin1);
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final WindowState hwin1 = createWindow(null, TYPE_BASE_APPLICATION, homeActivity, "hwin1");
+        homeActivity.addWindow(hwin1);
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
-        appWindow.addWindow(win1);
+        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
+        activity.addWindow(win1);
         final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
                 mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */);
         spyOn(mDisplayContent.mWallpaperController);
@@ -256,15 +256,15 @@
     @Test
     public void testDeferCancelAnimation() throws Exception {
         mWm.setRecentsAnimationController(mController);
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
-        appWindow.addWindow(win1);
-        assertEquals(appWindow.getTask().getTopVisibleAppToken(), appWindow);
-        assertEquals(appWindow.findMainWindow(), win1);
+        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
+        activity.addWindow(win1);
+        assertEquals(activity.getTask().getTopVisibleActivity(), activity);
+        assertEquals(activity.findMainWindow(), win1);
 
-        mController.addAnimation(appWindow.getTask(), false /* isRecentTaskInvisible */);
-        assertTrue(mController.isAnimatingTask(appWindow.getTask()));
+        mController.addAnimation(activity.getTask(), false /* isRecentTaskInvisible */);
+        assertTrue(mController.isAnimatingTask(activity.getTask()));
 
         mController.setDeferredCancel(true /* deferred */, false /* screenshot */);
         mController.cancelAnimationWithScreenshot(false /* screenshot */);
@@ -279,15 +279,15 @@
     @Test
     public void testDeferCancelAnimationWithScreenShot() throws Exception {
         mWm.setRecentsAnimationController(mController);
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
-        appWindow.addWindow(win1);
-        assertEquals(appWindow.getTask().getTopVisibleAppToken(), appWindow);
-        assertEquals(appWindow.findMainWindow(), win1);
+        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
+        activity.addWindow(win1);
+        assertEquals(activity.getTask().getTopVisibleActivity(), activity);
+        assertEquals(activity.findMainWindow(), win1);
 
-        mController.addAnimation(appWindow.getTask(), false /* isRecentTaskInvisible */);
-        assertTrue(mController.isAnimatingTask(appWindow.getTask()));
+        mController.addAnimation(activity.getTask(), false /* isRecentTaskInvisible */);
+        assertTrue(mController.isAnimatingTask(activity.getTask()));
 
         spyOn(mWm.mTaskSnapshotController);
         doNothing().when(mWm.mTaskSnapshotController).notifyAppVisibilityChanged(any(),
@@ -311,20 +311,20 @@
     @Test
     public void testShouldAnimateWhenNoCancelWithDeferredScreenshot() {
         mWm.setRecentsAnimationController(mController);
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
-        appWindow.addWindow(win1);
-        assertEquals(appWindow.getTask().getTopVisibleAppToken(), appWindow);
-        assertEquals(appWindow.findMainWindow(), win1);
+        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
+        activity.addWindow(win1);
+        assertEquals(activity.getTask().getTopVisibleActivity(), activity);
+        assertEquals(activity.findMainWindow(), win1);
 
-        mController.addAnimation(appWindow.getTask(), false /* isRecentTaskInvisible */);
-        assertTrue(mController.isAnimatingTask(appWindow.getTask()));
+        mController.addAnimation(activity.getTask(), false /* isRecentTaskInvisible */);
+        assertTrue(mController.isAnimatingTask(activity.getTask()));
 
-        // Assume appWindow transition should animate when no
+        // Assume activity transition should animate when no
         // IRecentsAnimationController#setCancelWithDeferredScreenshot called.
         assertFalse(mController.shouldDeferCancelWithScreenshot());
-        assertTrue(appWindow.shouldAnimate(TRANSIT_ACTIVITY_CLOSE));
+        assertTrue(activity.shouldAnimate(TRANSIT_ACTIVITY_CLOSE));
     }
 
     private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
index efc2fd6..a23425f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
@@ -106,7 +106,7 @@
                 "overrideWindow");
         overrideWindow.mAttrs.packageName = "com.android.test";
         overrideWindow.mAttrs.preferredDisplayModeId = LOW_MODE_ID;
-        overrideWindow.mAppToken.mSurfaceAnimator.startAnimation(
+        overrideWindow.mActivityRecord.mSurfaceAnimator.startAnimation(
                 overrideWindow.getPendingTransaction(), mock(AnimationAdapter.class),
                 false /* hidden */);
         mPolicy.addNonHighRefreshRatePackage("com.android.test");
@@ -122,7 +122,7 @@
         mPolicy.addNonHighRefreshRatePackage("com.android.test");
         assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(cameraUsingWindow));
 
-        cameraUsingWindow.mAppToken.mSurfaceAnimator.startAnimation(
+        cameraUsingWindow.mActivityRecord.mSurfaceAnimator.startAnimation(
                 cameraUsingWindow.getPendingTransaction(), mock(AnimationAdapter.class),
                 false /* hidden */);
         assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 3b9c3bb..e353903 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -91,9 +91,9 @@
     @Test
     public void testRun() throws Exception {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        mDisplayContent.mOpeningApps.add(win.mAppToken);
+        mDisplayContent.mOpeningApps.add(win.mActivityRecord);
         try {
-            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mAppToken,
+            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                     new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
             adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
             mController.goodToGo();
@@ -110,8 +110,8 @@
             final RemoteAnimationTarget app = appsCaptor.getValue()[0];
             assertEquals(new Point(50, 100), app.position);
             assertEquals(new Rect(50, 100, 150, 150), app.sourceContainerBounds);
-            assertEquals(win.mAppToken.getPrefixOrderIndex(), app.prefixOrderIndex);
-            assertEquals(win.mAppToken.getTask().mTaskId, app.taskId);
+            assertEquals(win.mActivityRecord.getPrefixOrderIndex(), app.prefixOrderIndex);
+            assertEquals(win.mActivityRecord.getTask().mTaskId, app.taskId);
             assertEquals(mMockLeash, app.leash);
             assertEquals(win.mWinAnimator.mLastClipRect, app.clipRect);
             assertEquals(false, app.isTranslucent);
@@ -129,7 +129,7 @@
     @Test
     public void testCancel() throws Exception {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mAppToken,
+        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                 new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
         adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
         mController.goodToGo();
@@ -142,7 +142,7 @@
     @FlakyTest(bugId = 133372977)
     public void testTimeout() throws Exception {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mAppToken,
+        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                 new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
         adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
         mController.goodToGo();
@@ -161,7 +161,7 @@
             final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
                     "testWin");
             final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
-                    win.mAppToken, new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
+                    win.mActivityRecord, new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
             adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
             mController.goodToGo();
 
@@ -189,7 +189,7 @@
     @Test
     public void testNotReallyStarted() {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        mController.createRemoteAnimationRecord(win.mAppToken,
+        mController.createRemoteAnimationRecord(win.mActivityRecord,
                 new Point(50, 100), new Rect(50, 100, 150, 150), null);
         mController.goodToGo();
         verifyNoMoreInteractionsExceptAsBinder(mMockRunner);
@@ -199,9 +199,9 @@
     public void testOneNotStarted() throws Exception {
         final WindowState win1 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin1");
         final WindowState win2 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin2");
-        mController.createRemoteAnimationRecord(win1.mAppToken,
+        mController.createRemoteAnimationRecord(win1.mActivityRecord,
                 new Point(50, 100), new Rect(50, 100, 150, 150), null);
-        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win2.mAppToken,
+        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win2.mActivityRecord,
                 new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
         adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
         mController.goodToGo();
@@ -221,10 +221,10 @@
     @Test
     public void testRemovedBeforeStarted() {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mAppToken,
+        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                 new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
         adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
-        win.mAppToken.removeImmediately();
+        win.mActivityRecord.removeImmediately();
         mController.goodToGo();
         verifyNoMoreInteractionsExceptAsBinder(mMockRunner);
         verify(mFinishedCallback).onAnimationFinished(eq(adapter));
@@ -233,10 +233,10 @@
     @Test
     public void testChange() throws Exception {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        mDisplayContent.mChangingApps.add(win.mAppToken);
+        mDisplayContent.mChangingApps.add(win.mActivityRecord);
         try {
             final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
-                    win.mAppToken, new Point(50, 100), new Rect(50, 100, 150, 150),
+                    win.mActivityRecord, new Point(50, 100), new Rect(50, 100, 150, 150),
                     new Rect(0, 0, 200, 200));
             assertNotNull(record.mThumbnailAdapter);
             ((AnimationAdapter) record.mAdapter)
@@ -284,9 +284,9 @@
         spyOn(mDisplayContent.mWallpaperController);
         doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        mDisplayContent.mOpeningApps.add(win.mAppToken);
+        mDisplayContent.mOpeningApps.add(win.mActivityRecord);
         try {
-            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mAppToken,
+            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                     new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
             adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
             mController.goodToGo();
@@ -312,9 +312,9 @@
         spyOn(mDisplayContent.mWallpaperController);
         doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        mDisplayContent.mOpeningApps.add(win.mAppToken);
+        mDisplayContent.mOpeningApps.add(win.mActivityRecord);
         try {
-            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mAppToken,
+            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                     new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
             adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
             mController.goodToGo();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 2b1c4ff..979aab6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -237,7 +237,7 @@
         mDeferFinishAnimatable.mFinishedCallbackCalled = false;
 
         // Simulate the first deferred callback is executed from
-        // {@link AnimatingAppWindowTokenRegistry#endDeferringFinished}.
+        // {@link AnimatingActivityRegistry#endDeferringFinished}.
         firstDeferFinishCallback.run();
         // The second animation should not be finished.
         assertFalse(mDeferFinishAnimatable.mFinishedCallbackCalled);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index ef9821b..fa1f435 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -415,8 +415,8 @@
             final AppOpsService aos = mock(AppOpsService.class);
             doReturn(aos).when(this).getAppOpsService();
             // Make sure permission checks aren't overridden.
-            doReturn(AppOpsManager.MODE_DEFAULT)
-                    .when(aos).noteOperation(anyInt(), anyInt(), anyString());
+            doReturn(AppOpsManager.MODE_DEFAULT).when(aos).noteOperation(anyInt(), anyInt(),
+                    anyString(), nullable(String.class));
 
             // UserManagerService
             final UserManagerService ums = mock(UserManagerService.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index 3bedabc..bebb3ba 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -54,7 +54,7 @@
         mCache.putSnapshot(window.getTask(), createSnapshot());
         assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
                 false /* restoreFromDisk */, false /* reducedResolution */));
-        mCache.onAppRemoved(window.mAppToken);
+        mCache.onAppRemoved(window.mActivityRecord);
         assertNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
                 false /* restoreFromDisk */, false /* reducedResolution */));
     }
@@ -65,7 +65,7 @@
         mCache.putSnapshot(window.getTask(), createSnapshot());
         assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
                 false /* restoreFromDisk */, false /* reducedResolution */));
-        mCache.onAppDied(window.mAppToken);
+        mCache.onAppDied(window.mActivityRecord);
         assertNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
                 false /* restoreFromDisk */, false /* reducedResolution */));
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 113f3c8..3b11003 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -48,14 +48,14 @@
     public void testGetClosingApps_closing() {
         final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
                 "closingWindow");
-        closingWindow.mAppToken.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
+        closingWindow.mActivityRecord.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
                 true /* performLayout */, false /* isVoiceInteraction */);
-        final ArraySet<AppWindowToken> closingApps = new ArraySet<>();
-        closingApps.add(closingWindow.mAppToken);
+        final ArraySet<ActivityRecord> closingApps = new ArraySet<>();
+        closingApps.add(closingWindow.mActivityRecord);
         final ArraySet<Task> closingTasks = new ArraySet<>();
         mWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks);
         assertEquals(1, closingTasks.size());
-        assertEquals(closingWindow.mAppToken.getTask(), closingTasks.valueAt(0));
+        assertEquals(closingWindow.mActivityRecord.getTask(), closingTasks.valueAt(0));
     }
 
     @Test
@@ -64,12 +64,12 @@
                 "closingWindow");
         final WindowState openingWindow = createAppWindow(closingWindow.getTask(),
                 FIRST_APPLICATION_WINDOW, "openingWindow");
-        closingWindow.mAppToken.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
+        closingWindow.mActivityRecord.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
                 true /* performLayout */, false /* isVoiceInteraction */);
-        openingWindow.mAppToken.commitVisibility(null, true /* visible */, TRANSIT_UNSET,
+        openingWindow.mActivityRecord.commitVisibility(null, true /* visible */, TRANSIT_UNSET,
                 true /* performLayout */, false /* isVoiceInteraction */);
-        final ArraySet<AppWindowToken> closingApps = new ArraySet<>();
-        closingApps.add(closingWindow.mAppToken);
+        final ArraySet<ActivityRecord> closingApps = new ArraySet<>();
+        closingApps.add(closingWindow.mActivityRecord);
         final ArraySet<Task> closingTasks = new ArraySet<>();
         mWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks);
         assertEquals(0, closingTasks.size());
@@ -79,13 +79,13 @@
     public void testGetClosingApps_skipClosingAppsSnapshotTasks() {
         final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
                 "closingWindow");
-        closingWindow.mAppToken.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
+        closingWindow.mActivityRecord.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
                 true /* performLayout */, false /* isVoiceInteraction */);
-        final ArraySet<AppWindowToken> closingApps = new ArraySet<>();
-        closingApps.add(closingWindow.mAppToken);
+        final ArraySet<ActivityRecord> closingApps = new ArraySet<>();
+        closingApps.add(closingWindow.mActivityRecord);
         final ArraySet<Task> closingTasks = new ArraySet<>();
         mWm.mTaskSnapshotController.addSkipClosingAppSnapshotTasks(
-                Sets.newArraySet(closingWindow.mAppToken.getTask()));
+                Sets.newArraySet(closingWindow.mActivityRecord.getTask()));
         mWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks);
         assertEquals(0, closingTasks.size());
     }
@@ -94,7 +94,7 @@
     public void testGetSnapshotMode() {
         final WindowState disabledWindow = createWindow(null,
                 FIRST_APPLICATION_WINDOW, mDisplayContent, "disabledWindow");
-        disabledWindow.mAppToken.setDisablePreviewScreenshots(true);
+        disabledWindow.mActivityRecord.setDisablePreviewScreenshots(true);
         assertEquals(SNAPSHOT_MODE_APP_THEME,
                 mWm.mTaskSnapshotController.getSnapshotMode(disabledWindow.getTask()));
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
index 92ddb35..a66c79c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -54,8 +54,8 @@
         // Stack should contain visible app window to be considered visible.
         final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */);
         assertFalse(mPinnedStack.isVisible());
-        final AppWindowToken pinnedApp =
-                WindowTestUtils.createTestAppWindowToken(mDisplayContent);
+        final ActivityRecord pinnedApp =
+                WindowTestUtils.createTestActivityRecord(mDisplayContent);
         pinnedTask.addChild(pinnedApp, 0 /* addPos */);
         assertTrue(mPinnedStack.isVisible());
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 2eb6ea4..5b9a785 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -68,19 +68,19 @@
     public void testClosingAppDifferentStackOrientation() {
         final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
         final Task task1 = createTaskInStack(stack, 0 /* userId */);
-        AppWindowToken appWindowToken1 =
-                WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        task1.addChild(appWindowToken1, 0);
-        appWindowToken1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        ActivityRecord activity1 =
+                WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        task1.addChild(activity1, 0);
+        activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         final Task task2 = createTaskInStack(stack, 1 /* userId */);
-        AppWindowToken appWindowToken2 =
-                WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        task2.addChild(appWindowToken2, 0);
-        appWindowToken2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
+        ActivityRecord activity2=
+                WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        task2.addChild(activity2, 0);
+        activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
 
         assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
-        mDisplayContent.mClosingApps.add(appWindowToken2);
+        mDisplayContent.mClosingApps.add(activity2);
         assertEquals(SCREEN_ORIENTATION_LANDSCAPE, stack.getOrientation());
     }
 
@@ -88,16 +88,16 @@
     public void testMoveTaskToBackDifferentStackOrientation() {
         final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
         final Task task1 = createTaskInStack(stack, 0 /* userId */);
-        AppWindowToken appWindowToken1 =
-                WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        task1.addChild(appWindowToken1, 0);
-        appWindowToken1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        ActivityRecord activity1 =
+                WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        task1.addChild(activity1, 0);
+        activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         final Task task2 = createTaskInStack(stack, 1 /* userId */);
-        AppWindowToken appWindowToken2 =
-                WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        task2.addChild(appWindowToken2, 0);
-        appWindowToken2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
+        ActivityRecord activity2 =
+                WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        task2.addChild(activity2, 0);
+        activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
 
         assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
         task2.setSendingToBottom(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index f117ff0..2ba1834 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -46,22 +46,22 @@
     public void testRemoveContainer() {
         final TaskStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
         final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1);
-        final AppWindowToken appToken =
-                WindowTestUtils.createAppWindowTokenInTask(mDisplayContent, task);
+        final ActivityRecord activity =
+                WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
 
         task.removeIfPossible();
         // Assert that the container was removed.
         assertNull(task.getParent());
         assertEquals(0, task.getChildCount());
-        assertNull(appToken.getParent());
+        assertNull(activity.getParent());
     }
 
     @Test
     public void testRemoveContainer_deferRemoval() {
         final TaskStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
         final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1);
-        final AppWindowToken appToken =
-                WindowTestUtils.createAppWindowTokenInTask(mDisplayContent, task);
+        final ActivityRecord activity =
+                WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
 
         task.mShouldDeferRemoval = true;
 
@@ -70,12 +70,12 @@
         // until the task window container is removed.
         assertNotNull(task.getParent());
         assertNotEquals(0, task.getChildCount());
-        assertNotNull(appToken.getParent());
+        assertNotNull(activity.getParent());
 
         task.removeImmediately();
         assertNull(task.getParent());
         assertEquals(0, task.getChildCount());
-        assertNull(appToken.getParent());
+        assertNull(activity.getParent());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index 09e5027..6a94137 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -115,4 +115,8 @@
     @Override
     public void showInsets(int types, boolean fromIme) throws RemoteException {
     }
+
+    @Override
+    public void hideInsets(int types, boolean fromIme) throws RemoteException {
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 761f73e..aa6c14e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -117,16 +117,16 @@
             CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
             int logo, int windowFlags, Configuration overrideConfig, int displayId) {
         final com.android.server.wm.WindowState window;
-        final AppWindowToken atoken;
+        final ActivityRecord activity;
         final WindowManagerService wm = mWmSupplier.get();
         synchronized (wm.mGlobalLock) {
-            atoken = wm.mRoot.getAppWindowToken(appToken);
+            activity = wm.mRoot.getActivityRecord(appToken);
             IWindow iWindow = mock(IWindow.class);
             doReturn(mock(IBinder.class)).when(iWindow).asBinder();
-            window = WindowTestsBase.createWindow(null, TYPE_APPLICATION_STARTING, atoken,
+            window = WindowTestsBase.createWindow(null, TYPE_APPLICATION_STARTING, activity,
                     "Starting window", 0 /* ownerId */, false /* internalWindows */, wm,
                     mock(Session.class), iWindow, mPowerManagerWrapper);
-            atoken.startingWindow = window;
+            activity.startingWindow = window;
         }
         if (mRunnableWhenAddingSplashScreen != null) {
             mRunnableWhenAddingSplashScreen.run();
@@ -134,8 +134,8 @@
         }
         return () -> {
             synchronized (wm.mGlobalLock) {
-                atoken.removeChild(window);
-                atoken.startingWindow = null;
+                activity.removeChild(window);
+                activity.startingWindow = null;
             }
         };
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 2e86178..e8a4e90 100644
--- a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -44,10 +44,10 @@
 
     @Test
     public void testFlow() {
-        final AppWindowToken token = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(token);
-        mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(token);
-        mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(token);
+        final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
+        mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(activity);
+        mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(activity);
 
         // Make sure our handler processed the message.
         waitHandlerIdle(mWm.mH);
@@ -56,14 +56,14 @@
 
     @Test
     public void testMultiple() {
-        final AppWindowToken token1 = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        final AppWindowToken token2 = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(token1);
-        mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(token1);
-        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(token2);
-        mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(token1);
-        mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(token2);
-        mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(token2);
+        final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity1);
+        mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(activity1);
+        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity2);
+        mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(activity1);
+        mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(activity2);
+        mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(activity2);
 
         // Make sure our handler processed the message.
         waitHandlerIdle(mWm.mH);
@@ -72,17 +72,17 @@
 
     @Test
     public void testClear() {
-        final AppWindowToken token = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(token);
+        final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
         mDisplayContent.mUnknownAppVisibilityController.clear();
         assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
     }
 
     @Test
     public void testAppRemoved() {
-        final AppWindowToken token = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(token);
-        mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(token);
+        final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
+        mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(activity);
         assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 3563feb..5c547c2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -422,10 +422,10 @@
         // Now simulate switch to fullscreen for letterboxed app.
         final int xInset = logicalWidth / 10;
         final Rect cf = new Rect(xInset, 0, logicalWidth - xInset, logicalHeight);
-        Configuration config = new Configuration(w.mAppToken.getRequestedOverrideConfiguration());
+        Configuration config = new Configuration(w.mActivityRecord.getRequestedOverrideConfiguration());
         config.windowConfiguration.setBounds(cf);
         config.windowConfiguration.setAppBounds(cf);
-        w.mAppToken.onRequestedOverrideConfigurationChanged(config);
+        w.mActivityRecord.onRequestedOverrideConfigurationChanged(config);
         pf.set(0, 0, logicalWidth, logicalHeight);
         task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         task.setBounds(null);
@@ -549,11 +549,11 @@
         attrs.width = width;
         attrs.height = height;
 
-        AppWindowToken token = createAppWindowToken(mTestDisplayContent,
+        ActivityRecord activity = createActivityRecord(mTestDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
 
-        FrameTestWindowState ws = new FrameTestWindowState(mWm, mIWindow, token, attrs);
-        token.addWindow(ws);
+        FrameTestWindowState ws = new FrameTestWindowState(mWm, mIWindow, activity, attrs);
+        activity.addWindow(ws);
         return ws;
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index a09253a..1a4562b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -303,11 +303,11 @@
     @Test
     public void testPrepareWindowToDisplayDuringRelayout() {
         // Call prepareWindowToDisplayDuringRelayout for a window without FLAG_TURN_SCREEN_ON before
-        // calling setCurrentLaunchCanTurnScreenOn for windows with flag in the same appWindowToken.
-        final AppWindowToken appWindowToken = createAppWindowToken(mDisplayContent,
+        // calling setCurrentLaunchCanTurnScreenOn for windows with flag in the same activity.
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final WindowState first = createWindow(null, TYPE_APPLICATION, appWindowToken, "first");
-        final WindowState second = createWindow(null, TYPE_APPLICATION, appWindowToken, "second");
+        final WindowState first = createWindow(null, TYPE_APPLICATION, activity, "first");
+        final WindowState second = createWindow(null, TYPE_APPLICATION, activity, "second");
         second.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
 
         testPrepareWindowToDisplayDuringRelayout(first, false /* expectedWakeupCalled */,
@@ -316,8 +316,8 @@
                 false /* expectedCurrentLaunchCanTurnScreenOn */);
 
         // Call prepareWindowToDisplayDuringRelayout for two window that have FLAG_TURN_SCREEN_ON
-        // from the same appWindowToken. Only one should trigger the wakeup.
-        appWindowToken.setCurrentLaunchCanTurnScreenOn(true);
+        // from the same activity. Only one should trigger the wakeup.
+        activity.setCurrentLaunchCanTurnScreenOn(true);
         first.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
         second.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
 
@@ -328,15 +328,15 @@
 
         // Without window flags, the state of ActivityRecord.canTurnScreenOn should still be able to
         // turn on the screen.
-        appWindowToken.setCurrentLaunchCanTurnScreenOn(true);
+        activity.setCurrentLaunchCanTurnScreenOn(true);
         first.mAttrs.flags &= ~WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
-        doReturn(true).when(appWindowToken).canTurnScreenOn();
+        doReturn(true).when(activity).canTurnScreenOn();
 
         testPrepareWindowToDisplayDuringRelayout(first, true /* expectedWakeupCalled */,
                 false /* expectedCurrentLaunchCanTurnScreenOn */);
 
         // Call prepareWindowToDisplayDuringRelayout for a windows that are not children of an
-        // appWindowToken. Both windows have the FLAG_TURNS_SCREEN_ON so both should call wakeup
+        // activity. Both windows have the FLAG_TURNS_SCREEN_ON so both should call wakeup
         final WindowToken windowToken = WindowTestUtils.createTestWindowToken(FIRST_SUB_WINDOW,
                 mDisplayContent);
         final WindowState firstWindow = createWindow(null, TYPE_APPLICATION, windowToken,
@@ -371,7 +371,7 @@
         }
         // If wakeup is expected to be called, the currentLaunchCanTurnScreenOn should be false
         // because the state will be consumed.
-        assertThat(appWindow.mAppToken.currentLaunchCanTurnScreenOn(),
+        assertThat(appWindow.mActivityRecord.currentLaunchCanTurnScreenOn(),
                 is(expectedCurrentLaunchCanTurnScreenOn));
     }
 
@@ -555,7 +555,7 @@
 
         // Mock active recents animation
         RecentsAnimationController recentsController = mock(RecentsAnimationController.class);
-        when(recentsController.isAnimatingTask(win0.mAppToken.getTask())).thenReturn(true);
+        when(recentsController.isAnimatingTask(win0.mActivityRecord.getTask())).thenReturn(true);
         mWm.setRecentsAnimationController(recentsController);
         assertTrue(win0.cantReceiveTouchInput());
     }
@@ -563,14 +563,14 @@
     @Test
     public void testCantReceiveTouchWhenAppTokenHiddenRequested() {
         final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
-        win0.mAppToken.hiddenRequested = true;
+        win0.mActivityRecord.hiddenRequested = true;
         assertTrue(win0.cantReceiveTouchInput());
     }
 
     @Test
     public void testCantReceiveTouchWhenShouldIgnoreInput() {
         final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
-        win0.mAppToken.getStack().setAdjustedForMinimizedDock(1 /* Any non 0 value works */);
+        win0.mActivityRecord.getStack().setAdjustedForMinimizedDock(1 /* Any non 0 value works */);
         assertTrue(win0.cantReceiveTouchInput());
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index c627c19..4fbf820 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -19,20 +19,16 @@
 import static android.app.AppOpsManager.OP_NONE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static com.android.server.wm.ActivityTestsBase.ActivityBuilder.createIntentAndActivityInfo;
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
 
 import android.app.ActivityManager;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
 import android.os.IBinder;
-import android.util.Pair;
 import android.view.IWindow;
 import android.view.WindowManager;
 
+import com.android.server.wm.ActivityTestsBase.ActivityBuilder;
+
 /**
  * A collection of static functions that provide access to WindowManager related test functionality.
  */
@@ -50,24 +46,21 @@
         }
     }
 
-    /** Creates an {@link AppWindowToken} and adds it to the specified {@link Task}. */
-    static AppWindowToken createAppWindowTokenInTask(DisplayContent dc, Task task) {
-        final AppWindowToken newToken = createTestAppWindowToken(dc);
-        task.addChild(newToken, POSITION_TOP);
-        return newToken;
+    /** Creates an {@link ActivityRecord} and adds it to the specified {@link Task}. */
+    static ActivityRecord createActivityRecordInTask(DisplayContent dc, Task task) {
+        final ActivityRecord activity = createTestActivityRecord(dc);
+        task.addChild(activity, POSITION_TOP);
+        return activity;
     }
 
-    static AppWindowToken createTestAppWindowToken(DisplayContent dc) {
+    static ActivityRecord createTestActivityRecord(DisplayContent dc) {
         synchronized (dc.mWmService.mGlobalLock) {
-            Pair<Intent, ActivityInfo> pair = createIntentAndActivityInfo();
-            final AppWindowToken token = new AppWindowToken(dc.mWmService,
-                    dc.mWmService.mAtmService, new ActivityRecord.Token(pair.first), pair.second,
-                    null, pair.first, dc);
-            token.setOccludesParent(true);
-            token.setHidden(false);
-            token.hiddenRequested = false;
-            spyOn(token);
-            return token;
+            final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService).build();
+            activity.onDisplayChanged(dc);
+            activity.setOccludesParent(true);
+            activity.setHidden(false);
+            activity.hiddenRequested = false;
+            return activity;
         }
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 4c4b21e..af9c510 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -200,22 +200,22 @@
                 return WindowTestUtils.createTestWindowToken(type, dc);
             }
 
-            return createAppWindowToken(dc, windowingMode, activityType);
+            return createActivityRecord(dc, windowingMode, activityType);
         }
     }
 
-    AppWindowToken createAppWindowToken(DisplayContent dc, int windowingMode, int activityType) {
-        return createTestAppWindowToken(dc, windowingMode, activityType);
+    ActivityRecord createActivityRecord(DisplayContent dc, int windowingMode, int activityType) {
+        return createTestActivityRecord(dc, windowingMode, activityType);
     }
 
-    AppWindowToken createTestAppWindowToken(DisplayContent dc, int
+    ActivityRecord createTestActivityRecord(DisplayContent dc, int
             windowingMode, int activityType) {
         final TaskStack stack = createTaskStackOnDisplay(windowingMode, activityType, dc);
         final Task task = createTaskInStack(stack, 0 /* userId */);
-        final AppWindowToken appWindowToken =
-                WindowTestUtils.createTestAppWindowToken(dc);
-        task.addChild(appWindowToken, 0);
-        return appWindowToken;
+        final ActivityRecord activity =
+                WindowTestUtils.createTestActivityRecord(dc);
+        task.addChild(activity, 0);
+        return activity;
     }
 
     WindowState createWindow(WindowState parent, int type, String name) {
@@ -244,9 +244,10 @@
 
     WindowState createAppWindow(Task task, int type, String name) {
         synchronized (mWm.mGlobalLock) {
-            final AppWindowToken token = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-            task.addChild(token, 0);
-            return createWindow(null, type, token, name);
+            final ActivityRecord activity =
+                    WindowTestUtils.createTestActivityRecord(mDisplayContent);
+            task.addChild(activity, 0);
+            return createWindow(null, type, activity, name);
         }
     }
 
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index ecee709..2cd207f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -97,8 +97,6 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
 import java.util.Arrays;
@@ -191,11 +189,6 @@
                     event.mPackage = packageName;
                     reportEventOrAddToQueue(userId, event);
                 }
-
-                @Override
-                public void onParoleStateChanged(boolean isParoleOn) {
-
-                }
             };
 
     public UsageStatsService(Context context) {
@@ -1426,7 +1419,7 @@
                     Binder.getCallingUid(), userId);
             final long token = Binder.clearCallingIdentity();
             try {
-                return mAppStandby.isAppIdleFilteredOrParoled(
+                return mAppStandby.isAppIdleFiltered(
                         packageName, userId,
                         SystemClock.elapsedRealtime(), obfuscateInstantApps);
             } finally {
@@ -1995,11 +1988,6 @@
         }
 
         @Override
-        public boolean isAppIdleParoleOn() {
-            return mAppStandby.isParoledOrCharging();
-        }
-
-        @Override
         public void prepareShutdown() {
             // This method *WILL* do IO work, but we must block until it is finished or else
             // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
@@ -2015,7 +2003,6 @@
         @Override
         public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
             mAppStandby.addListener(listener);
-            listener.onParoleStateChanged(isAppIdleParoleOn());
         }
 
         @Override
diff --git a/startop/apps/test/Android.bp b/startop/apps/test/Android.bp
index a806320..2ff26b8 100644
--- a/startop/apps/test/Android.bp
+++ b/startop/apps/test/Android.bp
@@ -17,12 +17,14 @@
 android_app {
     name: "startop_test_app",
     srcs: [
+        "src/ComplexLayoutInflationActivity.java",
         "src/CPUIntensive.java",
         "src/EmptyActivity.java",
-        "src/LayoutInflationActivity.java",
-        "src/ComplexLayoutInflationActivity.java",
         "src/FrameLayoutInflationActivity.java",
+        "src/LayoutInflationActivity.java",
+        "src/NonInteractiveSystemServerBenchmarkActivity.java",
         "src/SystemServerBenchmarkActivity.java",
+        "src/SystemServerBenchmarks.java",
         "src/TextViewInflationActivity.java",
     ],
     sdk_version: "26", // Android O (8.0) and higher
diff --git a/startop/apps/test/AndroidManifest.xml b/startop/apps/test/AndroidManifest.xml
index 15785d4..ebe2584 100644
--- a/startop/apps/test/AndroidManifest.xml
+++ b/startop/apps/test/AndroidManifest.xml
@@ -84,6 +84,14 @@
             </intent-filter>
         </activity>
 
+        <activity
+            android:label="Non-interactive SystemServer Benchmark"
+            android:name=".NonInteractiveSystemServerBenchmarkActivity"
+            android:exported="true" />
+
     </application>
 
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
 </manifest>
diff --git a/startop/apps/test/README.md b/startop/apps/test/README.md
index dadc66a..949dff7 100644
--- a/startop/apps/test/README.md
+++ b/startop/apps/test/README.md
@@ -24,3 +24,14 @@
 inflation.
 
     adb shell am start -n com.android.startop.test/.ComplexLayoutInflationActivity
+
+## NonInteractiveSystemServerBenchmark
+
+This activity is for running microbenchmarks from the command line. Run as follows:
+
+   adb shell am start -W -n com.android.startop.test .NonInteractiveSystemServerBenchmarkActivity
+
+It takes awhile (and there's currently no automated way to make sure it's done),
+but when it finishes, you can get the results like this:
+
+    adb shell cat /sdcard/Android/data/com.android.startop.test/files/benchmark.csv
diff --git a/startop/apps/test/src/NonInteractiveSystemServerBenchmarkActivity.java b/startop/apps/test/src/NonInteractiveSystemServerBenchmarkActivity.java
new file mode 100644
index 0000000..a2dc2cf
--- /dev/null
+++ b/startop/apps/test/src/NonInteractiveSystemServerBenchmarkActivity.java
@@ -0,0 +1,71 @@
+/*
+ * 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.startop.test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+import java.util.ArrayList;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.GridLayout;
+import android.widget.TextView;
+
+public class NonInteractiveSystemServerBenchmarkActivity extends Activity {
+    ArrayList<CharSequence> benchmarkNames = new ArrayList();
+    ArrayList<Runnable> benchmarkThunks = new ArrayList();
+
+    PrintStream out;
+
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        SystemServerBenchmarks.initializeBenchmarks(this, (name, thunk) -> {
+            benchmarkNames.add(name);
+            benchmarkThunks.add(thunk);
+        });
+
+        try {
+            out = new PrintStream(new File(getExternalFilesDir(null), "benchmark.csv"));
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+        out.println("Name,Mean,Stdev");
+        runBenchmarks(0);
+    }
+
+    void runBenchmarks(int i) {
+        if (i < benchmarkNames.size()) {
+            SystemServerBenchmarks.runBenchmarkInBackground(benchmarkThunks.get(i),
+                    (mean, stdev) -> {
+                        out.printf("%s,%.0f,%.0f\n", benchmarkNames.get(i), mean, stdev);
+                        runBenchmarks(i + 1);
+                    });
+        }
+    }
+}
diff --git a/startop/apps/test/src/SystemServerBenchmarkActivity.java b/startop/apps/test/src/SystemServerBenchmarkActivity.java
index c8d9fde..75ea69b 100644
--- a/startop/apps/test/src/SystemServerBenchmarkActivity.java
+++ b/startop/apps/test/src/SystemServerBenchmarkActivity.java
@@ -31,13 +31,25 @@
 import android.widget.GridLayout;
 import android.widget.TextView;
 
+public class SystemServerBenchmarkActivity extends Activity implements BenchmarkRunner {
+    private GridLayout benchmarkList;
 
-class Benchmark {
-    // Time limit to run benchmarks in seconds
-    public static final int TIME_LIMIT = 5;
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.system_server_benchmark_page);
 
-    public Benchmark(ViewGroup parent, CharSequence name, Runnable thunk) {
-        Context context = parent.getContext();
+        benchmarkList = findViewById(R.id.benchmark_list);
+
+        SystemServerBenchmarks.initializeBenchmarks(this, this);
+    }
+
+    /**
+     * Adds a benchmark to the set to run.
+     *
+     * @param name A short name that shows up in the UI or benchmark results
+     */
+    public void addBenchmark(CharSequence name, Runnable thunk) {
+        Context context = benchmarkList.getContext();
         Button button = new Button(context);
         TextView mean = new TextView(context);
         TextView stdev = new TextView(context);
@@ -50,165 +62,14 @@
             mean.setText("Running...");
             stdev.setText("");
 
-            new AsyncTask() {
-                double resultMean = 0;
-                double resultStdev = 0;
-
-                @Override
-                protected Object doInBackground(Object... _args) {
-                    long startTime = System.nanoTime();
-                    int count = 0;
-
-                    // Run benchmark
-                    while (true) {
-                        long elapsed = -System.nanoTime();
-                        thunk.run();
-                        elapsed += System.nanoTime();
-
-                        count++;
-                        double elapsedVariance = (double) elapsed - resultMean;
-                        resultMean += elapsedVariance / count;
-                        resultStdev += elapsedVariance * ((double) elapsed - resultMean);
-
-                        if (System.nanoTime() - startTime > TIME_LIMIT * 1e9) {
-                            break;
-                        }
-                    }
-                    resultStdev = Math.sqrt(resultStdev / (count - 1));
-
-                    return null;
-                }
-
-                @Override
-                protected void onPostExecute(Object _result) {
-                    mean.setText(String.format("%.3f", resultMean / 1e6));
-                    stdev.setText(String.format("%.3f", resultStdev / 1e6));
-                }
-            }.execute(new Object());
-        });
-
-        parent.addView(button);
-        parent.addView(mean);
-        parent.addView(stdev);
-    }
-}
-
-public class SystemServerBenchmarkActivity extends Activity {
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.system_server_benchmark_page);
-
-        GridLayout benchmarkList = findViewById(R.id.benchmark_list);
-
-        new Benchmark(benchmarkList, "Empty", () -> {
-        });
-
-        new Benchmark(benchmarkList, "CPU Intensive (1 thread)", () -> {
-            CPUIntensive.doSomeWork(1);
-        });
-
-        new Benchmark(benchmarkList, "CPU Intensive (2 thread)", () -> {
-            CPUIntensive.doSomeWork(2);
-        });
-
-        new Benchmark(benchmarkList, "CPU Intensive (4 thread)", () -> {
-            CPUIntensive.doSomeWork(4);
-        });
-
-        new Benchmark(benchmarkList, "CPU Intensive (8 thread)", () -> {
-            CPUIntensive.doSomeWork(8);
-        });
-
-        PackageManager pm = getPackageManager();
-        new Benchmark(benchmarkList, "getInstalledApplications", () -> {
-            pm.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY);
-        });
-
-        new Benchmark(benchmarkList, "getInstalledPackages", () -> {
-            pm.getInstalledPackages(PackageManager.GET_ACTIVITIES);
-        });
-
-        new Benchmark(benchmarkList, "getPackageInfo", () -> {
-            try {
-                pm.getPackageInfo("com.android.startop.test", 0);
-            } catch (NameNotFoundException e) {
-                throw new RuntimeException(e);
-            }
-        });
-
-        new Benchmark(benchmarkList, "getApplicationInfo", () -> {
-            try {
-                pm.getApplicationInfo("com.android.startop.test", 0);
-            } catch (NameNotFoundException e) {
-                throw new RuntimeException(e);
-            }
-        });
-
-        try {
-            ApplicationInfo app = pm.getApplicationInfo("com.android.startop.test", 0);
-            new Benchmark(benchmarkList, "getResourcesForApplication", () -> {
-                try {
-                    pm.getResourcesForApplication(app);
-                } catch (NameNotFoundException e) {
-                    throw new RuntimeException(e);
-                }
+            SystemServerBenchmarks.runBenchmarkInBackground(thunk, (resultMean, resultStdev) -> {
+                mean.setText(String.format("%.3f", resultMean / 1e6));
+                stdev.setText(String.format("%.3f", resultStdev / 1e6));
             });
-
-            new Benchmark(benchmarkList, "getPackagesForUid", () -> {
-                pm.getPackagesForUid(app.uid);
-            });
-        } catch (NameNotFoundException e) {
-            throw new RuntimeException(e);
-        }
-
-        ComponentName component = new ComponentName(this, this.getClass());
-        new Benchmark(benchmarkList, "getActivityInfo", () -> {
-            try {
-                pm.getActivityInfo(component, PackageManager.GET_META_DATA);
-            } catch (NameNotFoundException e) {
-                throw new RuntimeException(e);
-            }
         });
 
-        new Benchmark(benchmarkList, "getLaunchIntentForPackage", () -> {
-            pm.getLaunchIntentForPackage("com.android.startop.test");
-        });
-
-        new Benchmark(benchmarkList, "getPackageUid", () -> {
-            try {
-                pm.getPackageUid("com.android.startop.test", 0);
-            } catch (NameNotFoundException e) {
-                throw new RuntimeException(e);
-            }
-        });
-
-        new Benchmark(benchmarkList, "checkPermission", () -> {
-            // Check for the first permission I could find.
-            pm.checkPermission("android.permission.SEND_SMS", "com.android.startop.test");
-        });
-
-        new Benchmark(benchmarkList, "checkSignatures", () -> {
-            // Compare with settings, since settings is on both AOSP and Master builds
-            pm.checkSignatures("com.android.settings", "com.android.startop.test");
-        });
-
-        Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
-        new Benchmark(benchmarkList, "queryBroadcastReceivers", () -> {
-            pm.queryBroadcastReceivers(intent, 0);
-        });
-
-        new Benchmark(benchmarkList, "hasSystemFeature", () -> {
-            pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
-        });
-
-        new Benchmark(benchmarkList, "resolveService", () -> {
-            pm.resolveService(intent, 0);
-        });
-
-        ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
-        new Benchmark(benchmarkList, "getRunningAppProcesses", () -> {
-            am.getRunningAppProcesses();
-        });
-
+        benchmarkList.addView(button);
+        benchmarkList.addView(mean);
+        benchmarkList.addView(stdev);
     }
 }
diff --git a/startop/apps/test/src/SystemServerBenchmarks.java b/startop/apps/test/src/SystemServerBenchmarks.java
new file mode 100644
index 0000000..5918503
--- /dev/null
+++ b/startop/apps/test/src/SystemServerBenchmarks.java
@@ -0,0 +1,261 @@
+/*
+ * 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.startop.test;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.ConnectivityManager;
+import android.os.AsyncTask;
+import android.os.PowerManager;
+import android.os.Process;
+import android.os.UserManager;
+
+/**
+ * An interface for running benchmarks and collecting results. Used so we can have both an
+ * interactive runner and a non-interactive runner.
+ */
+interface BenchmarkRunner {
+    void addBenchmark(CharSequence name, Runnable thunk);
+}
+
+interface ResultListener {
+    /**
+     * Called when a benchmark result is ready
+     *
+     * @param mean  The average iteration time in nanoseconds
+     * @param stdev The standard deviation of iteration times in nanoseconds
+     */
+    void onResult(double mean, double stdev);
+}
+
+class SystemServerBenchmarks {
+    // Time limit to run benchmarks in seconds
+    public static final int TIME_LIMIT = 5;
+
+    static void initializeBenchmarks(Activity parent, BenchmarkRunner benchmarks) {
+        final String packageName = parent.getPackageName();
+
+        benchmarks.addBenchmark("Empty", () -> {
+        });
+
+        benchmarks.addBenchmark("CPU Intensive (1 thread)", () -> {
+            CPUIntensive.doSomeWork(1);
+        });
+
+        benchmarks.addBenchmark("CPU Intensive (2 thread)", () -> {
+            CPUIntensive.doSomeWork(2);
+        });
+
+        benchmarks.addBenchmark("CPU Intensive (4 thread)", () -> {
+            CPUIntensive.doSomeWork(4);
+        });
+
+        benchmarks.addBenchmark("CPU Intensive (8 thread)", () -> {
+            CPUIntensive.doSomeWork(8);
+        });
+
+        PackageManager pm = parent.getPackageManager();
+        benchmarks.addBenchmark("getInstalledApplications", () -> {
+            pm.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY);
+        });
+
+        benchmarks.addBenchmark("getInstalledPackages", () -> {
+            pm.getInstalledPackages(PackageManager.GET_ACTIVITIES);
+        });
+
+        benchmarks.addBenchmark("getPackageInfo", () -> {
+            try {
+                pm.getPackageInfo(packageName, 0);
+            } catch (NameNotFoundException e) {
+                throw new RuntimeException(e);
+            }
+        });
+
+        benchmarks.addBenchmark("getApplicationInfo", () -> {
+            try {
+                pm.getApplicationInfo(packageName, 0);
+            } catch (NameNotFoundException e) {
+                throw new RuntimeException(e);
+            }
+        });
+
+        try {
+            ApplicationInfo app = pm.getApplicationInfo(packageName, 0);
+            benchmarks.addBenchmark("getResourcesForApplication", () -> {
+                try {
+                    pm.getResourcesForApplication(app);
+                } catch (NameNotFoundException e) {
+                    throw new RuntimeException(e);
+                }
+            });
+
+            benchmarks.addBenchmark("getPackagesForUid", () -> {
+                pm.getPackagesForUid(app.uid);
+            });
+        } catch (NameNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+
+        ComponentName component = new ComponentName(parent, parent.getClass());
+        benchmarks.addBenchmark("getActivityInfo", () -> {
+            try {
+                pm.getActivityInfo(component, PackageManager.GET_META_DATA);
+            } catch (NameNotFoundException e) {
+                throw new RuntimeException(e);
+            }
+        });
+
+        benchmarks.addBenchmark("getLaunchIntentForPackage", () -> {
+            pm.getLaunchIntentForPackage(packageName);
+        });
+
+        benchmarks.addBenchmark("getPackageUid", () -> {
+            try {
+                pm.getPackageUid(packageName, 0);
+            } catch (NameNotFoundException e) {
+                throw new RuntimeException(e);
+            }
+        });
+
+        benchmarks.addBenchmark("checkPermission", () -> {
+            // Check for the first permission I could find.
+            pm.checkPermission("android.permission.SEND_SMS", packageName);
+        });
+
+        benchmarks.addBenchmark("checkSignatures", () -> {
+            // Compare with settings, since settings is on both AOSP and Master builds
+            pm.checkSignatures("com.android.settings", packageName);
+        });
+
+        Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
+        benchmarks.addBenchmark("queryBroadcastReceivers", () -> {
+            pm.queryBroadcastReceivers(intent, 0);
+        });
+
+        benchmarks.addBenchmark("hasSystemFeature", () -> {
+            pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
+        });
+
+        benchmarks.addBenchmark("resolveService", () -> {
+            pm.resolveService(intent, 0);
+        });
+
+        ActivityManager am = (ActivityManager) parent.getSystemService(Context.ACTIVITY_SERVICE);
+        benchmarks.addBenchmark("getRunningAppProcesses", () -> {
+            am.getRunningAppProcesses();
+        });
+
+        // We use PendingIntent.getCreatorPackage, since
+        // getPackageIntentForSender is not public to us, but getCreatorPackage
+        // is just a thin wrapper around it.
+        PendingIntent pi = PendingIntent.getActivity(parent, 0, new Intent(), 0);
+        benchmarks.addBenchmark("getPackageIntentForSender", () -> {
+            pi.getCreatorPackage();
+        });
+
+        PowerManager pwr = (PowerManager) parent.getSystemService(Context.POWER_SERVICE);
+        PowerManager.WakeLock wl = pwr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "benchmark tag");
+        benchmarks.addBenchmark("WakeLock Acquire/Release", () -> {
+            wl.acquire();
+            wl.release();
+        });
+
+        AppOpsManager appOps = (AppOpsManager) parent.getSystemService(Context.APP_OPS_SERVICE);
+        int uid = Process.myUid();
+        benchmarks.addBenchmark("AppOpsService.checkOperation", () -> {
+            appOps.checkOp(AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE, uid, packageName);
+        });
+
+        benchmarks.addBenchmark("AppOpsService.checkPackage", () -> {
+            appOps.checkPackage(uid, packageName);
+        });
+
+        benchmarks.addBenchmark("AppOpsService.noteOperation", () -> {
+            appOps.noteOp(AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE, uid, packageName);
+        });
+
+        benchmarks.addBenchmark("AppOpsService.noteProxyOperation", () -> {
+            appOps.noteProxyOp(AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE, packageName);
+        });
+
+        UserManager userManager = (UserManager) parent.getSystemService(Context.USER_SERVICE);
+        benchmarks.addBenchmark("isUserUnlocked", () -> {
+            userManager.isUserUnlocked();
+        });
+
+        benchmarks.addBenchmark("getIntentSender", () -> {
+            pi.getIntentSender();
+        });
+
+        ConnectivityManager cm = (ConnectivityManager) parent
+                .getSystemService(Context.CONNECTIVITY_SERVICE);
+        benchmarks.addBenchmark("getActiveNetworkInfo", () -> {
+            cm.getActiveNetworkInfo();
+        });
+    }
+
+    /**
+     * A helper method for benchark runners to actually run the benchmark and gather stats
+     *
+     * @param thunk    The code whose performance we want to measure
+     * @param reporter What to do with the results
+     */
+    static void runBenchmarkInBackground(Runnable thunk, ResultListener reporter) {
+        new AsyncTask() {
+            double resultMean = 0;
+            double resultStdev = 0;
+
+            @Override
+            protected Object doInBackground(Object... _args) {
+                long startTime = System.nanoTime();
+                int count = 0;
+
+                // Run benchmark
+                while (true) {
+                    long elapsed = -System.nanoTime();
+                    thunk.run();
+                    elapsed += System.nanoTime();
+
+                    count++;
+                    double elapsedVariance = (double) elapsed - resultMean;
+                    resultMean += elapsedVariance / count;
+                    resultStdev += elapsedVariance * ((double) elapsed - resultMean);
+
+                    if (System.nanoTime() - startTime > TIME_LIMIT * 1e9) {
+                        break;
+                    }
+                }
+                resultStdev = Math.sqrt(resultStdev / (count - 1));
+
+                return null;
+            }
+
+            @Override
+            protected void onPostExecute(Object _result) {
+                reporter.onResult(resultMean, resultStdev);
+            }
+        }.execute(new Object());
+    }
+}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java b/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java
index acf9946..59f4d56 100644
--- a/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java
+++ b/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java
@@ -33,6 +33,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
 import java.util.Objects;
 
 /**
@@ -86,10 +87,14 @@
     public static final class IntentStarted extends AppLaunchEvent {
         @NonNull
         public final Intent intent;
+        public final long timestampNs;
 
-        public IntentStarted(@SequenceId long sequenceId, Intent intent) {
+        public IntentStarted(@SequenceId long sequenceId,
+                             Intent intent,
+                             long timestampNs) {
             super(sequenceId);
             this.intent = intent;
+            this.timestampNs = timestampNs;
 
             Objects.requireNonNull(intent, "intent");
         }
@@ -98,14 +103,16 @@
         public boolean equals(Object other) {
             if (other instanceof IntentStarted) {
                 return intent.equals(((IntentStarted)other).intent) &&
-                        super.equals(other);
+                       timestampNs == ((IntentStarted)other).timestampNs &&
+                       super.equals(other);
             }
             return false;
         }
 
         @Override
         protected String toStringBody() {
-            return ", intent=" + intent.toString();
+            return ", intent=" + intent.toString() +
+                   " , timestampNs=" + Long.toString(timestampNs);
         }
 
 
@@ -113,11 +120,13 @@
         protected void writeToParcelImpl(Parcel p, int flags) {
             super.writeToParcelImpl(p, flags);
             IntentProtoParcelable.write(p, intent, flags);
+            p.writeLong(timestampNs);
         }
 
         IntentStarted(Parcel p) {
             super(p);
             intent = IntentProtoParcelable.create(p);
+            timestampNs = p.readLong();
         }
     }
 
@@ -154,8 +163,8 @@
         @Override
         public boolean equals(Object other) {
             if (other instanceof BaseWithActivityRecordData) {
-                return activityRecordSnapshot.equals(
-                        ((BaseWithActivityRecordData)other).activityRecordSnapshot) &&
+                return (Arrays.equals(activityRecordSnapshot,
+                      ((BaseWithActivityRecordData)other).activityRecordSnapshot)) &&
                         super.equals(other);
             }
             return false;
@@ -163,7 +172,7 @@
 
         @Override
         protected String toStringBody() {
-            return ", " + activityRecordSnapshot.toString();
+            return ", " + new String(activityRecordSnapshot);
         }
 
         @Override
@@ -200,7 +209,7 @@
 
         @Override
         protected String toStringBody() {
-            return ", temperature=" + Integer.toString(temperature);
+            return super.toStringBody() + ", temperature=" + Integer.toString(temperature);
         }
 
         @Override
@@ -216,18 +225,39 @@
     }
 
     public static final class ActivityLaunchFinished extends BaseWithActivityRecordData {
+        public final long timestampNs;
+
         public ActivityLaunchFinished(@SequenceId long sequenceId,
-                @NonNull @ActivityRecordProto byte[] snapshot) {
+                @NonNull @ActivityRecordProto byte[] snapshot,
+                long timestampNs) {
             super(sequenceId, snapshot);
+            this.timestampNs = timestampNs;
         }
 
         @Override
         public boolean equals(Object other) {
-            if (other instanceof ActivityLaunched) {
-                return super.equals(other);
+            if (other instanceof ActivityLaunchFinished) {
+                return timestampNs == ((ActivityLaunchFinished)other).timestampNs &&
+                       super.equals(other);
             }
             return false;
         }
+
+        @Override
+        protected String toStringBody() {
+            return super.toStringBody() + ", timestampNs=" + Long.toString(timestampNs);
+        }
+
+        @Override
+        protected void writeToParcelImpl(Parcel p, int flags) {
+           super.writeToParcelImpl(p, flags);
+           p.writeLong(timestampNs);
+        }
+
+        ActivityLaunchFinished(Parcel p) {
+            super(p);
+            timestampNs = p.readLong();
+        }
     }
 
      public static class ActivityLaunchCancelled extends AppLaunchEvent {
@@ -242,8 +272,8 @@
         @Override
         public boolean equals(Object other) {
             if (other instanceof ActivityLaunchCancelled) {
-                return Objects.equals(activityRecordSnapshot,
-                        ((ActivityLaunchCancelled)other).activityRecordSnapshot) &&
+                return Arrays.equals(activityRecordSnapshot,
+                    ((ActivityLaunchCancelled)other).activityRecordSnapshot) &&
                         super.equals(other);
             }
             return false;
@@ -251,7 +281,7 @@
 
         @Override
         protected String toStringBody() {
-            return ", " + activityRecordSnapshot.toString();
+            return super.toStringBody() + ", " + new String(activityRecordSnapshot);
         }
 
         @Override
@@ -275,6 +305,42 @@
         }
     }
 
+    public static final class ReportFullyDrawn extends BaseWithActivityRecordData {
+        public final long timestampNs;
+
+        public ReportFullyDrawn(@SequenceId long sequenceId,
+                @NonNull @ActivityRecordProto byte[] snapshot,
+                long timestampNs) {
+            super(sequenceId, snapshot);
+            this.timestampNs = timestampNs;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (other instanceof ReportFullyDrawn) {
+                return timestampNs == ((ReportFullyDrawn)other).timestampNs &&
+                        super.equals(other);
+            }
+            return false;
+        }
+
+        @Override
+        protected String toStringBody() {
+            return super.toStringBody() + ", timestampNs=" + Long.toString(timestampNs);
+        }
+
+        @Override
+        protected void writeToParcelImpl(Parcel p, int flags) {
+           super.writeToParcelImpl(p, flags);
+           p.writeLong(timestampNs);
+        }
+
+        ReportFullyDrawn(Parcel p) {
+            super(p);
+            timestampNs = p.readLong();
+        }
+    }
+
     @Override
     public @ContentsFlags int describeContents() { return 0; }
 
@@ -348,6 +414,7 @@
             ActivityLaunched.class,
             ActivityLaunchFinished.class,
             ActivityLaunchCancelled.class,
+            ReportFullyDrawn.class,
     };
 
     public static class ActivityRecordProtoParcelable {
diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
index 902da4c..f753548 100644
--- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
+++ b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
@@ -315,19 +315,19 @@
         // All callbacks occur on the same background thread. Don't synchronize explicitly.
 
         @Override
-        public void onIntentStarted(@NonNull Intent intent) {
+        public void onIntentStarted(@NonNull Intent intent, long timestampNs) {
             // #onIntentStarted [is the only transition that] initiates a new launch sequence.
             ++mSequenceId;
 
             if (DEBUG) {
-                Log.v(TAG, String.format("AppLaunchObserver#onIntentStarted(%d, %s)",
-                        mSequenceId, intent));
+                Log.v(TAG, String.format("AppLaunchObserver#onIntentStarted(%d, %s, %d)",
+                        mSequenceId, intent, timestampNs));
             }
 
             invokeRemote(mIorapRemote,
                 (IIorap remote) ->
                     remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
-                        new AppLaunchEvent.IntentStarted(mSequenceId, intent))
+                        new AppLaunchEvent.IntentStarted(mSequenceId, intent, timestampNs))
             );
         }
 
@@ -374,16 +374,34 @@
         }
 
         @Override
-        public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] activity) {
+        public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] activity,
+            long timestampNs) {
             if (DEBUG) {
-                Log.v(TAG, String.format("AppLaunchObserver#onActivityLaunchFinished(%d, %s)",
-                        mSequenceId, activity));
+                Log.v(TAG, String.format("AppLaunchObserver#onActivityLaunchFinished(%d, %s, %d)",
+                        mSequenceId, activity, timestampNs));
             }
 
             invokeRemote(mIorapRemote,
                 (IIorap remote) ->
                     remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
-                        new AppLaunchEvent.ActivityLaunchFinished(mSequenceId, activity))
+                        new AppLaunchEvent.ActivityLaunchFinished(mSequenceId,
+                            activity,
+                            timestampNs))
+            );
+        }
+
+        @Override
+        public void onReportFullyDrawn(@NonNull @ActivityRecordProto byte[] activity,
+            long timestampNs) {
+            if (DEBUG) {
+                Log.v(TAG, String.format("AppLaunchObserver#onReportFullyDrawn(%d, %s, %d)",
+                        mSequenceId, activity, timestampNs));
+            }
+
+            invokeRemote(mIorapRemote,
+                (IIorap remote) ->
+                    remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
+                        new AppLaunchEvent.ReportFullyDrawn(mSequenceId, activity, timestampNs))
             );
         }
     }
diff --git a/startop/iorap/tests/src/com/google/android/startop/iorap/AppLaunchEventTest.kt b/startop/iorap/tests/src/com/google/android/startop/iorap/AppLaunchEventTest.kt
new file mode 100644
index 0000000..51e407d
--- /dev/null
+++ b/startop/iorap/tests/src/com/google/android/startop/iorap/AppLaunchEventTest.kt
@@ -0,0 +1,181 @@
+/*
+ * 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.google.android.startop.iorap
+
+import android.content.Intent;
+import android.net.Uri
+import android.os.Parcel
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import com.google.android.startop.iorap.AppLaunchEvent;
+import com.google.android.startop.iorap.AppLaunchEvent.ActivityLaunched
+import com.google.android.startop.iorap.AppLaunchEvent.ActivityLaunchCancelled
+import com.google.android.startop.iorap.AppLaunchEvent.ActivityLaunchFinished
+import com.google.android.startop.iorap.AppLaunchEvent.IntentStarted;
+import com.google.android.startop.iorap.AppLaunchEvent.IntentFailed;
+import com.google.android.startop.iorap.AppLaunchEvent.ReportFullyDrawn
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+
+/**
+ * Basic unit tests to test all of the [AppLaunchEvent]s in [com.google.android.startop.iorap].
+ */
+@SmallTest
+class AppLaunchEventTest {
+  /**
+   * Test for IntentStarted.
+   */
+  @Test
+  fun testIntentStarted() {
+    var intent = Intent()
+    val valid = IntentStarted(/* sequenceId= */2L, intent, /* timestampNs= */ 1L)
+    val copy = IntentStarted(/* sequenceId= */2L, intent, /* timestampNs= */ 1L)
+    val noneCopy1 = IntentStarted(/* sequenceId= */1L, intent, /* timestampNs= */ 1L)
+    val noneCopy2 = IntentStarted(/* sequenceId= */2L, intent, /* timestampNs= */ 2L)
+    val noneCopy3 = IntentStarted(/* sequenceId= */2L, Intent(), /* timestampNs= */ 1L)
+
+    // equals(Object other)
+    assertThat(valid).isEqualTo(copy)
+    assertThat(valid).isNotEqualTo(noneCopy1)
+    assertThat(valid).isNotEqualTo(noneCopy2)
+    assertThat(valid).isNotEqualTo(noneCopy3)
+
+    // test toString()
+    val result = valid.toString()
+    assertThat(result).isEqualTo("IntentStarted{sequenceId=2, intent=Intent {  } , timestampNs=1}")
+  }
+
+  /**
+   * Test for IntentFailed.
+   */
+  @Test
+  fun testIntentFailed() {
+    val valid = IntentFailed(/* sequenceId= */2L)
+    val copy = IntentFailed(/* sequenceId= */2L)
+    val noneCopy = IntentFailed(/* sequenceId= */1L)
+
+    // equals(Object other)
+    assertThat(valid).isEqualTo(copy)
+    assertThat(valid).isNotEqualTo(noneCopy)
+
+    // test toString()
+    val result = valid.toString()
+    assertThat(result).isEqualTo("IntentFailed{sequenceId=2}")
+  }
+
+  /**
+   * Test for ActivityLaunched.
+   */
+  @Test
+  fun testActivityLaunched() {
+    //var activityRecord =
+    val valid = ActivityLaunched(/* sequenceId= */2L, "test".toByteArray(),
+      /* temperature= */ 0)
+    val copy = ActivityLaunched(/* sequenceId= */2L, "test".toByteArray(),
+      /* temperature= */ 0)
+    val noneCopy1 = ActivityLaunched(/* sequenceId= */1L, "test".toByteArray(),
+      /* temperature= */ 0)
+    val noneCopy2 = ActivityLaunched(/* sequenceId= */1L, "test".toByteArray(),
+      /* temperature= */ 1)
+    val noneCopy3 = ActivityLaunched(/* sequenceId= */1L, "test1".toByteArray(),
+      /* temperature= */ 0)
+
+    // equals(Object other)
+    assertThat(valid).isEqualTo(copy)
+    assertThat(valid).isNotEqualTo(noneCopy1)
+    assertThat(valid).isNotEqualTo(noneCopy2)
+    assertThat(valid).isNotEqualTo(noneCopy3)
+
+    // test toString()
+    val result = valid.toString()
+    assertThat(result).isEqualTo("ActivityLaunched{sequenceId=2, test, temperature=0}")
+  }
+
+
+  /**
+   * Test for ActivityLaunchFinished.
+   */
+  @Test
+  fun testActivityLaunchFinished() {
+    val valid = ActivityLaunchFinished(/* sequenceId= */2L, "test".toByteArray(),
+      /* timestampNs= */ 1L)
+    val copy = ActivityLaunchFinished(/* sequenceId= */2L, "test".toByteArray(),
+      /* timestampNs= */ 1L)
+    val noneCopy1 = ActivityLaunchFinished(/* sequenceId= */1L, "test".toByteArray(),
+      /* timestampNs= */ 1L)
+    val noneCopy2 = ActivityLaunchFinished(/* sequenceId= */1L, "test".toByteArray(),
+      /* timestampNs= */ 2L)
+    val noneCopy3 = ActivityLaunchFinished(/* sequenceId= */2L, "test1".toByteArray(),
+      /* timestampNs= */ 1L)
+
+    // equals(Object other)
+    assertThat(valid).isEqualTo(copy)
+    assertThat(valid).isNotEqualTo(noneCopy1)
+    assertThat(valid).isNotEqualTo(noneCopy2)
+    assertThat(valid).isNotEqualTo(noneCopy3)
+
+    // test toString()
+    val result = valid.toString()
+    assertThat(result).isEqualTo("ActivityLaunchFinished{sequenceId=2, test, timestampNs=1}")
+  }
+
+  /**
+   * Test for ActivityLaunchCancelled.
+   */
+  @Test
+  fun testActivityLaunchCancelled() {
+    val valid = ActivityLaunchCancelled(/* sequenceId= */2L, "test".toByteArray())
+    val copy = ActivityLaunchCancelled(/* sequenceId= */2L, "test".toByteArray())
+    val noneCopy1 = ActivityLaunchCancelled(/* sequenceId= */1L, "test".toByteArray())
+    val noneCopy2 = ActivityLaunchCancelled(/* sequenceId= */2L, "test1".toByteArray())
+
+    // equals(Object other)
+    assertThat(valid).isEqualTo(copy)
+    assertThat(valid).isNotEqualTo(noneCopy1)
+    assertThat(valid).isNotEqualTo(noneCopy2)
+
+    // test toString()
+    val result = valid.toString()
+    assertThat(result).isEqualTo("ActivityLaunchCancelled{sequenceId=2, test}")
+  }
+
+  /**
+   * Test for ReportFullyDrawn.
+   */
+  @Test
+  fun testReportFullyDrawn() {
+    val valid = ReportFullyDrawn(/* sequenceId= */2L, "test".toByteArray(), /* timestampNs= */ 1L)
+    val copy = ReportFullyDrawn(/* sequenceId= */2L, "test".toByteArray(), /* timestampNs= */ 1L)
+    val noneCopy1 = ReportFullyDrawn(/* sequenceId= */1L, "test".toByteArray(),
+      /* timestampNs= */ 1L)
+    val noneCopy2 = ReportFullyDrawn(/* sequenceId= */1L, "test".toByteArray(),
+      /* timestampNs= */ 1L)
+    val noneCopy3 = ReportFullyDrawn(/* sequenceId= */2L, "test1".toByteArray(),
+      /* timestampNs= */ 1L)
+
+    // equals(Object other)
+    assertThat(valid).isEqualTo(copy)
+    assertThat(valid).isNotEqualTo(noneCopy1)
+    assertThat(valid).isNotEqualTo(noneCopy2)
+    assertThat(valid).isNotEqualTo(noneCopy3)
+
+    // test toString()
+    val result = valid.toString()
+    assertThat(result).isEqualTo("ReportFullyDrawn{sequenceId=2, test, timestampNs=1}")
+  }
+}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 5e71416..3f348a4 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -728,6 +728,7 @@
         }
 
         /** {@hide} */
+        @TestApi
         public String getTelecomCallId() {
             return mTelecomCallId;
         }
@@ -2137,6 +2138,9 @@
         }
 
         int state = parcelableCall.getState();
+        if (mTargetSdkVersion < Phone.SDK_VERSION_R && state == Call.STATE_SIMULATED_RINGING) {
+            state = Call.STATE_RINGING;
+        }
         boolean stateChanged = mState != state;
         if (stateChanged) {
             mState = state;
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index 0d97567..ef1c790 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -374,6 +374,8 @@
                         new ComponentName(getPackageName(), getClass().getName()));
             } else if (response.getSilenceCall()) {
                 mCallScreeningAdapter.silenceCall(callDetails.getTelecomCallId());
+            } else if (response.getShouldScreenCallFurther()) {
+                mCallScreeningAdapter.screenCallFurther(callDetails.getTelecomCallId());
             } else {
                 mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId());
             }
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 525b938..fa16b84 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -267,8 +267,13 @@
 
     /**
      * Speed up audio setup for MT call.
+     * <p>
+     * Used for IMS calls to indicate that mobile-terminated (incoming) call audio setup should take
+     * place as soon as the device answers the call, but prior to it being connected.  This is an
+     * optimization some IMS stacks depend on to ensure prompt setup of call audio.
      * @hide
      */
+    @SystemApi
     public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
 
     /**
@@ -305,6 +310,7 @@
      * device.
      * @hide
      */
+    @SystemApi
     public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 0x00200000;
 
     /**
@@ -346,28 +352,40 @@
 
     /**
      * Indicates that the current device callback number should be shown.
-     *
+     * <p>
+     * Supports Telephony calls where CDMA emergency callback mode is active.
      * @hide
      */
+    @SystemApi
     public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 1<<0;
 
     /**
      * Whether the call is a generic conference, where we do not know the precise state of
      * participants in the conference (eg. on CDMA).
-     *
+     * <p>
+     * Supports legacy telephony CDMA calls.
      * @hide
      */
+    @SystemApi
     public static final int PROPERTY_GENERIC_CONFERENCE = 1<<1;
 
     /**
      * Connection is using high definition audio.
-     * @hide
+     * <p>
+     * Indicates that the {@link Connection} is using a "high definition" audio codec.  This usually
+     * implies something like AMR wideband, but the interpretation of when a call is considered high
+     * definition is left to the {@link ConnectionService} to decide.
+     * <p>
+     * Translates to {@link android.telecom.Call.Details#PROPERTY_HIGH_DEF_AUDIO}.
      */
     public static final int PROPERTY_HIGH_DEF_AUDIO = 1<<2;
 
     /**
      * Connection is using WIFI.
-     * @hide
+     * <p>
+     * Used to indicate that a call is taking place over WIFI versus a carrier network.
+     * <p>
+     * Translates to {@link android.telecom.Call.Details#PROPERTY_WIFI}.
      */
     public static final int PROPERTY_WIFI = 1<<3;
 
@@ -394,8 +412,12 @@
 
     /**
      * Indicates that the connection represents a downgraded IMS conference.
+     * <p>
+     * This property is set when an IMS conference undergoes SRVCC and is re-added to Telecom as a
+     * new entity to indicate that the new connection was a conference.
      * @hide
      */
+    @SystemApi
     public static final int PROPERTY_IS_DOWNGRADED_CONFERENCE = 1<<6;
 
     /**
@@ -421,7 +443,9 @@
     /**
      * Set by the framework to indicate that the network has identified a Connection as an emergency
      * call.
-     * @hide
+     * <p>
+     * This is used for incoming (mobile-terminated) calls to indicate the call is from emergency
+     * services.
      */
     public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1 << 10;
 
@@ -429,8 +453,11 @@
      * Set by the framework to indicate that a Conference or Connection is hosted by a device other
      * than the current one.  Used in scenarios where the conference originator is the remote device
      * and the current device is a participant of that conference.
+     * <p>
+     * This property is specific to IMS conference calls originating in Telephony.
      * @hide
      */
+    @SystemApi
     public static final int PROPERTY_REMOTELY_HOSTED = 1 << 11;
 
     //**********************************************************************************************
@@ -483,8 +510,12 @@
     /**
      * Boolean connection extra key on a {@link Connection} which indicates that adding an
      * additional call is disallowed.
+     * <p>
+     * Used for mobile-network calls to identify scenarios where carrier requirements preclude
+     * adding another call at the current time.
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_DISABLE_ADD_CALL =
             "android.telecom.extra.DISABLE_ADD_CALL";
 
@@ -508,6 +539,9 @@
      * The TelephonyCS will ALSO try to add the existing connection to Telecom, except with the
      * ID it originally referred to the connection as.  Thus Telecom needs to know that the
      * Connection with ID {@code ConnMan@1} is really the same as {@code TelephonyCS@1}.
+     * <p>
+     * This is an internal Telecom framework concept and is not exposed outside of the Telecom
+     * framework.
      * @hide
      */
     public static final String EXTRA_ORIGINAL_CONNECTION_ID =
@@ -525,7 +559,6 @@
      * Connection event used to inform Telecom that it should play the on hold tone.  This is used
      * to play a tone when the peer puts the current call on hold.  Sent to Telecom via
      * {@link #sendConnectionEvent(String, Bundle)}.
-     * @hide
      */
     public static final String EVENT_ON_HOLD_TONE_START =
             "android.telecom.event.ON_HOLD_TONE_START";
@@ -534,7 +567,6 @@
      * Connection event used to inform Telecom that it should stop the on hold tone.  This is used
      * to stop a tone when the peer puts the current call on hold.  Sent to Telecom via
      * {@link #sendConnectionEvent(String, Bundle)}.
-     * @hide
      */
     public static final String EVENT_ON_HOLD_TONE_END =
             "android.telecom.event.ON_HOLD_TONE_END";
@@ -565,10 +597,9 @@
 
     /**
      * Connection event used to inform Telecom when a hold operation on a call has failed.
-     * Not intended for use by the UI at this time.
+     * <p>
      * Sent via {@link #sendConnectionEvent(String, Bundle)}.  The {@link Bundle} parameter is
      * expected to be null when this connection event is used.
-     * @hide
      */
     public static final String EVENT_CALL_HOLD_FAILED = "android.telecom.event.CALL_HOLD_FAILED";
 
@@ -578,7 +609,6 @@
      * <p>
      * Sent via {@link #sendConnectionEvent(String, Bundle)}.  The {@link Bundle} parameter is
      * expected to be null when this connection event is used.
-     * @hide
      */
     public static final String EVENT_MERGE_START = "android.telecom.event.MERGE_START";
 
@@ -588,7 +618,6 @@
      * <p>
      * Sent via {@link #sendConnectionEvent(String, Bundle)}.  The {@link Bundle} parameter is
      * expected to be null when this connection event is used.
-     * @hide
      */
     public static final String EVENT_MERGE_COMPLETE = "android.telecom.event.MERGE_COMPLETE";
 
@@ -600,7 +629,6 @@
      * call is being held locally on the device.  When a capable {@link ConnectionService} receives
      * signalling to indicate that the remote party has put the call on hold, it can send this
      * connection event.
-     * @hide
      */
     public static final String EVENT_CALL_REMOTELY_HELD =
             "android.telecom.event.CALL_REMOTELY_HELD";
@@ -613,7 +641,6 @@
      * call is being held locally on the device.  When a capable {@link ConnectionService} receives
      * signalling to indicate that the remote party has taken the call off hold, it can send this
      * connection event.
-     * @hide
      */
     public static final String EVENT_CALL_REMOTELY_UNHELD =
             "android.telecom.event.CALL_REMOTELY_UNHELD";
@@ -656,49 +683,6 @@
     private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
 
     /**
-     * Whether the given capabilities support the specified capability.
-     *
-     * @param capabilities A capability bit field.
-     * @param capability The capability to check capabilities for.
-     * @return Whether the specified capability is supported.
-     * @hide
-     */
-    public static boolean can(int capabilities, int capability) {
-        return (capabilities & capability) == capability;
-    }
-
-    /**
-     * Whether the capabilities of this {@code Connection} supports the specified capability.
-     *
-     * @param capability The capability to check capabilities for.
-     * @return Whether the specified capability is supported.
-     * @hide
-     */
-    public boolean can(int capability) {
-        return can(mConnectionCapabilities, capability);
-    }
-
-    /**
-     * Removes the specified capability from the set of capabilities of this {@code Connection}.
-     *
-     * @param capability The capability to remove from the set.
-     * @hide
-     */
-    public void removeCapability(int capability) {
-        mConnectionCapabilities &= ~capability;
-    }
-
-    /**
-     * Adds the specified capability to the set of capabilities of this {@code Connection}.
-     *
-     * @param capability The capability to add to the set.
-     * @hide
-     */
-    public void addCapability(int capability) {
-        mConnectionCapabilities |= capability;
-    }
-
-    /**
      * Renders a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
      *
      * @param capabilities A capability bit field.
@@ -727,67 +711,72 @@
             builder.append("Capabilities:");
         }
 
-        if (can(capabilities, CAPABILITY_HOLD)) {
+        if ((capabilities & CAPABILITY_HOLD) == CAPABILITY_HOLD) {
             builder.append(isLong ? " CAPABILITY_HOLD" : " hld");
         }
-        if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
+        if ((capabilities & CAPABILITY_SUPPORT_HOLD) == CAPABILITY_SUPPORT_HOLD) {
             builder.append(isLong ? " CAPABILITY_SUPPORT_HOLD" : " sup_hld");
         }
-        if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
+        if ((capabilities & CAPABILITY_MERGE_CONFERENCE) == CAPABILITY_MERGE_CONFERENCE) {
             builder.append(isLong ? " CAPABILITY_MERGE_CONFERENCE" : " mrg_cnf");
         }
-        if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
+        if ((capabilities & CAPABILITY_SWAP_CONFERENCE) == CAPABILITY_SWAP_CONFERENCE) {
             builder.append(isLong ? " CAPABILITY_SWAP_CONFERENCE" : " swp_cnf");
         }
-        if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
+        if ((capabilities & CAPABILITY_RESPOND_VIA_TEXT) == CAPABILITY_RESPOND_VIA_TEXT) {
             builder.append(isLong ? " CAPABILITY_RESPOND_VIA_TEXT" : " txt");
         }
-        if (can(capabilities, CAPABILITY_MUTE)) {
+        if ((capabilities & CAPABILITY_MUTE) == CAPABILITY_MUTE) {
             builder.append(isLong ? " CAPABILITY_MUTE" : " mut");
         }
-        if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
+        if ((capabilities & CAPABILITY_MANAGE_CONFERENCE) == CAPABILITY_MANAGE_CONFERENCE) {
             builder.append(isLong ? " CAPABILITY_MANAGE_CONFERENCE" : " mng_cnf");
         }
-        if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
+        if ((capabilities & CAPABILITY_SUPPORTS_VT_LOCAL_RX) == CAPABILITY_SUPPORTS_VT_LOCAL_RX) {
             builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_RX" : " VTlrx");
         }
-        if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
+        if ((capabilities & CAPABILITY_SUPPORTS_VT_LOCAL_TX) == CAPABILITY_SUPPORTS_VT_LOCAL_TX) {
             builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_TX" : " VTltx");
         }
-        if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
+        if ((capabilities & CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)
+                == CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL) {
             builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL" : " VTlbi");
         }
-        if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
+        if ((capabilities & CAPABILITY_SUPPORTS_VT_REMOTE_RX) == CAPABILITY_SUPPORTS_VT_REMOTE_RX) {
             builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_RX" : " VTrrx");
         }
-        if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
+        if ((capabilities & CAPABILITY_SUPPORTS_VT_REMOTE_TX) == CAPABILITY_SUPPORTS_VT_REMOTE_TX) {
             builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_TX" : " VTrtx");
         }
-        if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
+        if ((capabilities & CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)
+                == CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL) {
             builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL" : " VTrbi");
         }
-        if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
+        if ((capabilities & CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)
+                == CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO) {
             builder.append(isLong ? " CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO" : " !v2a");
         }
-        if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
+        if ((capabilities & CAPABILITY_SPEED_UP_MT_AUDIO) == CAPABILITY_SPEED_UP_MT_AUDIO) {
             builder.append(isLong ? " CAPABILITY_SPEED_UP_MT_AUDIO" : " spd_aud");
         }
-        if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
+        if ((capabilities & CAPABILITY_CAN_UPGRADE_TO_VIDEO) == CAPABILITY_CAN_UPGRADE_TO_VIDEO) {
             builder.append(isLong ? " CAPABILITY_CAN_UPGRADE_TO_VIDEO" : " a2v");
         }
-        if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
+        if ((capabilities & CAPABILITY_CAN_PAUSE_VIDEO) == CAPABILITY_CAN_PAUSE_VIDEO) {
             builder.append(isLong ? " CAPABILITY_CAN_PAUSE_VIDEO" : " paus_VT");
         }
-        if (can(capabilities, CAPABILITY_CONFERENCE_HAS_NO_CHILDREN)) {
+        if ((capabilities & CAPABILITY_CONFERENCE_HAS_NO_CHILDREN)
+                == CAPABILITY_CONFERENCE_HAS_NO_CHILDREN) {
             builder.append(isLong ? " CAPABILITY_SINGLE_PARTY_CONFERENCE" : " 1p_cnf");
         }
-        if (can(capabilities, CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION)) {
+        if ((capabilities & CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION)
+                == CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION) {
             builder.append(isLong ? " CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION" : " rsp_by_con");
         }
-        if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
+        if ((capabilities & CAPABILITY_CAN_PULL_CALL) == CAPABILITY_CAN_PULL_CALL) {
             builder.append(isLong ? " CAPABILITY_CAN_PULL_CALL" : " pull");
         }
-        if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
+        if ((capabilities & CAPABILITY_SUPPORT_DEFLECT) == CAPABILITY_SUPPORT_DEFLECT) {
             builder.append(isLong ? " CAPABILITY_SUPPORT_DEFLECT" : " sup_def");
         }
 
@@ -823,43 +812,44 @@
             builder.append("Properties:");
         }
 
-        if (can(properties, PROPERTY_SELF_MANAGED)) {
+        if ((properties & PROPERTY_SELF_MANAGED) == PROPERTY_SELF_MANAGED) {
             builder.append(isLong ? " PROPERTY_SELF_MANAGED" : " self_mng");
         }
 
-        if (can(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
+        if ((properties & PROPERTY_EMERGENCY_CALLBACK_MODE) == PROPERTY_EMERGENCY_CALLBACK_MODE) {
             builder.append(isLong ? " PROPERTY_EMERGENCY_CALLBACK_MODE" : " ecbm");
         }
 
-        if (can(properties, PROPERTY_HIGH_DEF_AUDIO)) {
+        if ((properties & PROPERTY_HIGH_DEF_AUDIO) == PROPERTY_HIGH_DEF_AUDIO) {
             builder.append(isLong ? " PROPERTY_HIGH_DEF_AUDIO" : " HD");
         }
 
-        if (can(properties, PROPERTY_WIFI)) {
+        if ((properties & PROPERTY_WIFI) == PROPERTY_WIFI) {
             builder.append(isLong ? " PROPERTY_WIFI" : " wifi");
         }
 
-        if (can(properties, PROPERTY_GENERIC_CONFERENCE)) {
+        if ((properties & PROPERTY_GENERIC_CONFERENCE) == PROPERTY_GENERIC_CONFERENCE) {
             builder.append(isLong ? " PROPERTY_GENERIC_CONFERENCE" : " gen_conf");
         }
 
-        if (can(properties, PROPERTY_IS_EXTERNAL_CALL)) {
+        if ((properties & PROPERTY_IS_EXTERNAL_CALL) == PROPERTY_IS_EXTERNAL_CALL) {
             builder.append(isLong ? " PROPERTY_IS_EXTERNAL_CALL" : " xtrnl");
         }
 
-        if (can(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
+        if ((properties & PROPERTY_HAS_CDMA_VOICE_PRIVACY) == PROPERTY_HAS_CDMA_VOICE_PRIVACY) {
             builder.append(isLong ? " PROPERTY_HAS_CDMA_VOICE_PRIVACY" : " priv");
         }
 
-        if (can(properties, PROPERTY_IS_RTT)) {
+        if ((properties & PROPERTY_IS_RTT) == PROPERTY_IS_RTT) {
             builder.append(isLong ? " PROPERTY_IS_RTT" : " rtt");
         }
 
-        if (can(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
+        if ((properties & PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)
+                == PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL) {
             builder.append(isLong ? " PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL" : " ecall");
         }
 
-        if (can(properties, PROPERTY_REMOTELY_HOSTED)) {
+        if ((properties & PROPERTY_REMOTELY_HOSTED) == PROPERTY_REMOTELY_HOSTED) {
             builder.append(isLong ? " PROPERTY_REMOTELY_HOSTED" : " remote_hst");
         }
 
@@ -889,16 +879,10 @@
         public void onConferenceablesChanged(
                 Connection c, List<Conferenceable> conferenceables) {}
         public void onConferenceChanged(Connection c, Conference conference) {}
-        /** @hide */
-        public void onConferenceParticipantsChanged(Connection c,
-                List<ConferenceParticipant> participants) {}
-        public void onConferenceStarted() {}
         public void onConferenceMergeFailed(Connection c) {}
         public void onExtrasChanged(Connection c, Bundle extras) {}
         public void onExtrasRemoved(Connection c, List<String> keys) {}
         public void onConnectionEvent(Connection c, String event, Bundle extras) {}
-        /** @hide */
-        public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {}
         public void onAudioRouteChanged(Connection c, int audioRoute, String bluetoothAddress) {}
         public void onRttInitiationSuccess(Connection c) {}
         public void onRttInitiationFailure(Connection c, int reason) {}
@@ -1815,11 +1799,15 @@
     /**
      * Returns the Telecom internal call ID associated with this connection.  Should only be used
      * for debugging and tracing purposes.
+     * <p>
+     * Note: Access to the Telecom internal call ID is used for logging purposes only; this API is
+     * provided to facilitate debugging of the Telephony stack only.
      *
-     * @return The Telecom call ID.
+     * @return The Telecom call ID, or {@code null} if it was not set.
      * @hide
      */
-    public final String getTelecomCallId() {
+    @SystemApi
+    public final @Nullable String getTelecomCallId() {
         return mTelecomCallId;
     }
 
@@ -1868,9 +1856,8 @@
      * {@link VideoProfile#STATE_RX_ENABLED}.
      *
      * @return The video state of the connection.
-     * @hide
      */
-    public final int getVideoState() {
+    public final @VideoProfile.VideoState int getVideoState() {
         return mVideoState;
     }
 
@@ -1926,11 +1913,16 @@
      * Retrieves the connection start time of the {@code Connnection}, if specified.  A value of
      * {@link Conference#CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the
      * start time of the conference.
+     * <p>
+     * Note: This is an implementation detail specific to IMS conference calls over a mobile
+     * network.
      *
-     * @return The time at which the {@code Connnection} was connected.
+     * @return The time at which the {@code Connnection} was connected. Will be a value as retrieved
+     * from {@link System#currentTimeMillis()}.
      *
      * @hide
      */
+    @SystemApi
     public final long getConnectTimeMillis() {
         return mConnectTimeMillis;
     }
@@ -1939,26 +1931,32 @@
      * Retrieves the connection start time of the {@link Connection}, if specified.  A value of
      * {@link Conference#CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the
      * start time of the conference.
-     *
+     * <p>
      * Based on the value of {@link SystemClock#elapsedRealtime()}, which ensures that wall-clock
      * changes do not impact the call duration.
+     * <p>
+     * Used internally in Telephony when migrating conference participant data for IMS conferences.
      *
      * @return The time at which the {@link Connection} was connected.
      *
      * @hide
      */
+    @SystemApi
     public final long getConnectElapsedTimeMillis() {
         return mConnectElapsedTimeMillis;
     }
 
     /**
      * Returns RIL voice radio technology used for current connection.
+     * <p>
+     * Used by the Telephony {@link ConnectionService}.
      *
      * @return the RIL voice radio technology used for current connection,
      *         see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
      *
      * @hide
      */
+    @SystemApi
     public final @RilRadioTechnology int getCallRadioTech() {
         int voiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
         Bundle extras = getExtras();
@@ -2038,11 +2036,16 @@
     /**
      * Sets the telecom call ID associated with this Connection.  The Telecom Call ID should be used
      * ONLY for debugging purposes.
+     * <p>
+     * Note: Access to the Telecom internal call ID is used for logging purposes only; this API is
+     * provided to facilitate debugging of the Telephony stack only.  Changing the ID via this
+     * method does NOT change any functionality in Telephony or Telecom and impacts only logging.
      *
      * @param callId The telecom call ID.
      * @hide
      */
-    public void setTelecomCallId(String callId) {
+    @SystemApi
+    public void setTelecomCallId(@NonNull String callId) {
         mTelecomCallId = callId;
     }
 
@@ -2379,12 +2382,15 @@
     /**
      * Sets the time at which a call became active on this Connection. This is set only
      * when a conference call becomes active on this connection.
+     * <p>
+     * Used by telephony to maintain calls associated with an IMS Conference.
      *
      * @param connectTimeMillis The connection time, in milliseconds.  Should be set using a value
      *                          obtained from {@link System#currentTimeMillis()}.
      *
      * @hide
      */
+    @SystemApi
     public final void setConnectTimeMillis(long connectTimeMillis) {
         mConnectTimeMillis = connectTimeMillis;
     }
@@ -2392,27 +2398,37 @@
     /**
      * Sets the time at which a call became active on this Connection. This is set only
      * when a conference call becomes active on this connection.
-     *
+     * <p>
+     * Used by telephony to maintain calls associated with an IMS Conference.
      * @param connectElapsedTimeMillis The connection time, in milliseconds.  Stored in the format
      *                              {@link SystemClock#elapsedRealtime()}.
      *
      * @hide
      */
+    @SystemApi
     public final void setConnectionStartElapsedRealTime(long connectElapsedTimeMillis) {
         mConnectElapsedTimeMillis = connectElapsedTimeMillis;
     }
 
     /**
      * Sets RIL voice radio technology used for current connection.
+     * <p>
+     * This property is set by the Telephony {@link ConnectionService}.
      *
      * @param vrat the RIL Voice Radio Technology used for current connection,
      *             see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
      *
      * @hide
      */
+    @SystemApi
     public final void setCallRadioTech(@RilRadioTechnology int vrat) {
-        putExtra(TelecomManager.EXTRA_CALL_NETWORK_TYPE,
+        Bundle extras = getExtras();
+        if (extras == null) {
+            extras = new Bundle();
+        }
+        extras.putInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE,
                 ServiceState.rilRadioTechnologyToNetworkType(vrat));
+        putExtras(extras);
         // Propagates the call radio technology to its parent {@link android.telecom.Conference}
         // This action only covers non-IMS CS conference calls.
         // For IMS PS call conference call, it can be updated via its host connection
@@ -2480,9 +2496,12 @@
     }
 
     /**
+     * Resets the CDMA connection time.
+     * <p>
+     * This is an implementation detail specific to legacy CDMA calls on mobile networks.
      * @hide
-     * Resets the cdma connection time.
      */
+    @SystemApi
     public final void resetConnectionTime() {
         for (Listener l : mListeners) {
             l.onConnectionTimeReset(this);
@@ -2522,13 +2541,6 @@
     }
 
     /**
-     * @hide
-     */
-    public final ConnectionService getConnectionService() {
-        return mConnectionService;
-    }
-
-    /**
      * Sets the conference that this connection is a part of. This will fail if the connection is
      * already part of a conference. {@link #resetConference} to un-set the conference first.
      *
@@ -2638,45 +2650,6 @@
     }
 
     /**
-     * Adds a boolean extra to this {@code Connection}.
-     *
-     * @param key The extra key.
-     * @param value The value.
-     * @hide
-     */
-    public final void putExtra(String key, boolean value) {
-        Bundle newExtras = new Bundle();
-        newExtras.putBoolean(key, value);
-        putExtras(newExtras);
-    }
-
-    /**
-     * Adds an integer extra to this {@code Connection}.
-     *
-     * @param key The extra key.
-     * @param value The value.
-     * @hide
-     */
-    public final void putExtra(String key, int value) {
-        Bundle newExtras = new Bundle();
-        newExtras.putInt(key, value);
-        putExtras(newExtras);
-    }
-
-    /**
-     * Adds a string extra to this {@code Connection}.
-     *
-     * @param key The extra key.
-     * @param value The value.
-     * @hide
-     */
-    public final void putExtra(String key, String value) {
-        Bundle newExtras = new Bundle();
-        newExtras.putString(key, value);
-        putExtras(newExtras);
-    }
-
-    /**
      * Removes extras from this {@code Connection}.
      *
      * @param keys The keys of the extras to remove.
@@ -3242,53 +3215,16 @@
     }
 
     /**
-     * Notifies listeners that the merge request failed.
-     *
-     * @hide
+     * Called by a {@link ConnectionService} to notify Telecom that a {@link Conference#onMerge()}
+     * request failed.
      */
-    protected final void notifyConferenceMergeFailed() {
+    public final void notifyConferenceMergeFailed() {
         for (Listener l : mListeners) {
             l.onConferenceMergeFailed(this);
         }
     }
 
     /**
-     * Notifies listeners of a change to conference participant(s).
-     *
-     * @param conferenceParticipants The participants.
-     * @hide
-     */
-    protected final void updateConferenceParticipants(
-            List<ConferenceParticipant> conferenceParticipants) {
-        for (Listener l : mListeners) {
-            l.onConferenceParticipantsChanged(this, conferenceParticipants);
-        }
-    }
-
-    /**
-     * Notifies listeners that a conference call has been started.
-     * @hide
-     */
-    protected void notifyConferenceStarted() {
-        for (Listener l : mListeners) {
-            l.onConferenceStarted();
-        }
-    }
-
-    /**
-     * Notifies listeners when a change has occurred to the Connection which impacts its ability to
-     * be a part of a conference call.
-     * @param isConferenceSupported {@code true} if the connection supports being part of a
-     *      conference call, {@code false} otherwise.
-     * @hide
-     */
-    protected void notifyConferenceSupportedChanged(boolean isConferenceSupported) {
-        for (Listener l : mListeners) {
-            l.onConferenceSupportedChanged(this, isConferenceSupported);
-        }
-    }
-
-    /**
      * Notifies listeners when phone account is changed. For example, when the PhoneAccount is
      * changed due to an emergency call being redialed.
      * @param pHandle The new PhoneAccountHandle for this connection.
@@ -3302,10 +3238,15 @@
 
     /**
      * Sets the {@link PhoneAccountHandle} associated with this connection.
+     * <p>
+     * Used by the Telephony {@link ConnectionService} to handle changes to the {@link PhoneAccount}
+     * which take place after call initiation (important for emergency calling scenarios).
      *
+     * @param phoneAccountHandle the phone account handle to set.
      * @hide
      */
-    public void setPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) {
+    @SystemApi
+    public void setPhoneAccountHandle(@NonNull PhoneAccountHandle phoneAccountHandle) {
         if (mPhoneAccountHandle != phoneAccountHandle) {
             mPhoneAccountHandle = phoneAccountHandle;
             notifyPhoneAccountChanged(phoneAccountHandle);
@@ -3314,10 +3255,16 @@
 
     /**
      * Returns the {@link PhoneAccountHandle} associated with this connection.
+     * <p>
+     * Used by the Telephony {@link ConnectionService} to handle changes to the {@link PhoneAccount}
+     * which take place after call initiation (important for emergency calling scenarios).
      *
+     * @return the phone account handle specified via
+     * {@link #setPhoneAccountHandle(PhoneAccountHandle)}, or {@code null} if none was set.
      * @hide
      */
-    public PhoneAccountHandle getPhoneAccountHandle() {
+    @SystemApi
+    public @Nullable PhoneAccountHandle getPhoneAccountHandle() {
         return mPhoneAccountHandle;
     }
 
@@ -3374,9 +3321,14 @@
 
     /**
      * Sets the direction of this connection.
+     * <p>
+     * Used when calling {@link ConnectionService#addExistingConnection} to specify the existing
+     * call direction.
+     *
      * @param callDirection The direction of this connection.
      * @hide
      */
+    @SystemApi
     public void setCallDirection(@Call.Details.CallDirection int callDirection) {
         mCallDirection = callDirection;
     }
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 0cc052e..2ecdb30 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -21,7 +21,6 @@
 import android.bluetooth.BluetoothDevice;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.util.ArrayMap;
 
 import java.util.Collections;
@@ -111,6 +110,10 @@
         public void onSilenceRinger(Phone phone) { }
     }
 
+    // TODO: replace all usages of this with the actual R constant from Build.VERSION_CODES
+    /** @hide */
+    public static final int SDK_VERSION_R = 30;
+
     // A Map allows us to track each Call by its Telecom-specified call ID
     private final Map<String, Call> mCallByTelecomCallId = new ArrayMap<>();
 
@@ -143,6 +146,12 @@
     }
 
     final void internalAddCall(ParcelableCall parcelableCall) {
+        if (mTargetSdkVersion < SDK_VERSION_R
+                && parcelableCall.getState() == Call.STATE_AUDIO_PROCESSING) {
+            Log.i(this, "Skipping adding audio processing call for sdk compatibility");
+            return;
+        }
+
         Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,
                 parcelableCall.getState(), mCallingPackage, mTargetSdkVersion);
         mCallByTelecomCallId.put(parcelableCall.getId(), call);
@@ -150,7 +159,7 @@
         checkCallTree(parcelableCall);
         call.internalUpdate(parcelableCall, mCallByTelecomCallId);
         fireCallAdded(call);
-     }
+    }
 
     final void internalRemoveCall(Call call) {
         mCallByTelecomCallId.remove(call.internalGetCallId());
@@ -164,12 +173,28 @@
     }
 
     final void internalUpdateCall(ParcelableCall parcelableCall) {
-         Call call = mCallByTelecomCallId.get(parcelableCall.getId());
-         if (call != null) {
-             checkCallTree(parcelableCall);
-             call.internalUpdate(parcelableCall, mCallByTelecomCallId);
-         }
-     }
+        if (mTargetSdkVersion < SDK_VERSION_R
+                && parcelableCall.getState() == Call.STATE_AUDIO_PROCESSING) {
+            Log.i(this, "removing audio processing call during update for sdk compatibility");
+            Call call = mCallByTelecomCallId.get(parcelableCall.getId());
+            if (call != null) {
+                internalRemoveCall(call);
+            }
+            return;
+        }
+
+        Call call = mCallByTelecomCallId.get(parcelableCall.getId());
+        if (call != null) {
+            checkCallTree(parcelableCall);
+            call.internalUpdate(parcelableCall, mCallByTelecomCallId);
+        } else {
+            // This call may have come out of audio processing. Try adding it if our target sdk
+            // version is low enough.
+            if (mTargetSdkVersion < SDK_VERSION_R) {
+                internalAddCall(parcelableCall);
+            }
+        }
+    }
 
     final void internalSetPostDialWait(String telecomId, String remaining) {
         Call call = mCallByTelecomCallId.get(telecomId);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 1d5c18d..047b220 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -526,6 +526,15 @@
             "default_vm_number_roaming_string";
 
     /**
+     * Where there is no preloaded voicemail number on a SIM card, specifies the carrier's default
+     * voicemail number while the device is both roaming and not registered for IMS.
+     * When empty string, no default voicemail number is specified for roaming network and
+     * unregistered state in IMS.
+     */
+    public static final String KEY_DEFAULT_VM_NUMBER_ROAMING_AND_IMS_UNREGISTERED_STRING =
+            "default_vm_number_roaming_and_ims_unregistered_string";
+
+    /**
      * Flag that specifies to use the user's own phone number as the voicemail number when there is
      * no pre-loaded voicemail number on the SIM card.
      * <p>
@@ -2817,7 +2826,7 @@
             "ping_test_before_data_switch_bool";
 
     /**
-     * Controls time in milli seconds until DcTracker reevaluates 5G connection state.
+     * Controls time in milliseconds until DcTracker reevaluates 5G connection state.
      * @hide
      */
     public static final String KEY_5G_WATCHDOG_TIME_MS_LONG =
@@ -3199,6 +3208,13 @@
     public static final String KEY_CARRIER_CERTIFICATE_STRING_ARRAY =
             "carrier_certificate_string_array";
 
+    /**
+     * DisconnectCause array to play busy tone. Value should be array of
+     * {@link android.telephony.DisconnectCause}.
+     */
+    public static final String KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY =
+            "disconnect_cause_play_busytone_int_array";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -3225,6 +3241,7 @@
         sDefaults.putBoolean(KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL, true);
         sDefaults.putString(KEY_DEFAULT_VM_NUMBER_STRING, "");
         sDefaults.putString(KEY_DEFAULT_VM_NUMBER_ROAMING_STRING, "");
+        sDefaults.putString(KEY_DEFAULT_VM_NUMBER_ROAMING_AND_IMS_UNREGISTERED_STRING, "");
         sDefaults.putBoolean(KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL, false);
         sDefaults.putBoolean(KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, true);
         sDefaults.putBoolean(KEY_VILTE_DATA_IS_METERED_BOOL, true);
@@ -3628,6 +3645,8 @@
         sDefaults.putBoolean(KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);
         sDefaults.putAll(Ims.getDefaults());
         sDefaults.putStringArray(KEY_CARRIER_CERTIFICATE_STRING_ARRAY, null);
+        sDefaults.putIntArray(KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY,
+                new int[] {4 /* BUSY */});
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellBroadcastService.java b/telephony/java/android/telephony/CellBroadcastService.java
index d5e447e..46eb9df 100644
--- a/telephony/java/android/telephony/CellBroadcastService.java
+++ b/telephony/java/android/telephony/CellBroadcastService.java
@@ -21,6 +21,7 @@
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
+import android.telephony.cdma.CdmaSmsCbProgramData;
 
 /**
  * A service which exposes the cell broadcast handling module to the system.
@@ -69,9 +70,11 @@
     /**
      * Handle a CDMA cell broadcast SMS message forwarded from the system.
      * @param slotIndex the index of the slot which received the message
-     * @param message the SMS PDU
+     * @param bearerData the CDMA SMS bearer data
+     * @param serviceCategory the CDMA SCPT service category
      */
-    public abstract void onCdmaCellBroadcastSms(int slotIndex, byte[] message);
+    public abstract void onCdmaCellBroadcastSms(int slotIndex, byte[] bearerData,
+            @CdmaSmsCbProgramData.Category int serviceCategory);
 
     /**
      * If overriding this method, call through to the super method for any unknown actions.
@@ -102,11 +105,14 @@
         /**
          * Handle a CDMA cell broadcast SMS.
          * @param slotIndex the index of the slot which received the broadcast
-         * @param message the SMS message PDU
+         * @param bearerData the CDMA SMS bearer data
+         * @param serviceCategory the CDMA SCPT service category
          */
         @Override
-        public void handleCdmaCellBroadcastSms(int slotIndex, byte[] message) {
-            CellBroadcastService.this.onCdmaCellBroadcastSms(slotIndex, message);
+        public void handleCdmaCellBroadcastSms(int slotIndex, byte[] bearerData,
+                int serviceCategory) {
+            CellBroadcastService.this.onCdmaCellBroadcastSms(slotIndex, bearerData,
+                    serviceCategory);
         }
     }
 }
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 7edc91c..18687d4 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -189,11 +189,15 @@
         mTimeStamp = ts;
     }
 
-    /** @hide */
+    /**
+     * @return a {@link CellIdentity} instance.
+     */
     @NonNull
     public abstract CellIdentity getCellIdentity();
 
-    /** @hide */
+    /**
+     * @return a {@link CellSignalStrength} instance.
+     */
     @NonNull
     public abstract CellSignalStrength getCellSignalStrength();
 
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index cdf01da..4dc54f0 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -245,9 +245,12 @@
     }
 
     /**
-     * Get the Ec/No as dB
+     * Get the Ec/No (Energy per chip over the noise spectral density) as dB.
      *
-     * @hide
+     * Reference: TS 25.133 Section 9.1.2.3
+     *
+     * @return the Ec/No of the measured cell in the range [-24, 1] or
+     * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable
      */
     public int getEcNo() {
         return mEcNo;
diff --git a/telephony/java/android/telephony/ICellBroadcastService.aidl b/telephony/java/android/telephony/ICellBroadcastService.aidl
index eff64a2..bcd6cc5 100644
--- a/telephony/java/android/telephony/ICellBroadcastService.aidl
+++ b/telephony/java/android/telephony/ICellBroadcastService.aidl
@@ -28,5 +28,5 @@
     oneway void handleGsmCellBroadcastSms(int slotId, in byte[] message);
 
     /** @see android.telephony.CellBroadcastService#onCdmaCellBroadcastSms */
-    oneway void handleCdmaCellBroadcastSms(int slotId, in byte[] message);
+    oneway void handleCdmaCellBroadcastSms(int slotId, in byte[] bearerData, int serviceCategory);
 }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index e288f25..8425ec1 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -47,22 +47,20 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelUuid;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.telephony.Annotation.NetworkType;
 import android.telephony.euicc.EuiccManager;
 import android.telephony.ims.ImsMmTelManager;
 import android.util.DisplayMetrics;
 import android.util.Log;
 
-import com.android.internal.telephony.IOnSubscriptionsChangedListener;
 import com.android.internal.telephony.ISetOpportunisticDataCallback;
 import com.android.internal.telephony.ISub;
-import com.android.internal.telephony.ITelephonyRegistry;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.Preconditions;
 
@@ -924,20 +922,24 @@
             OnSubscriptionsChangedListenerHandler(Looper looper) {
                 super(looper);
             }
-
-            @Override
-            public void handleMessage(Message msg) {
-                if (DBG) {
-                    log("handleMessage: invoke the overriden onSubscriptionsChanged()");
-                }
-                OnSubscriptionsChangedListener.this.onSubscriptionsChanged();
-            }
         }
 
-        private final Handler mHandler;
+        /**
+         * Posted executor callback on the handler associated with a given looper.
+         * The looper can be the calling thread's looper or the looper passed from the
+         * constructor {@link #OnSubscriptionsChangedListener(Looper)}.
+         */
+        private final HandlerExecutor mExecutor;
+
+        /**
+         * @hide
+         */
+        public HandlerExecutor getHandlerExecutor() {
+            return mExecutor;
+        }
 
         public OnSubscriptionsChangedListener() {
-            mHandler = new OnSubscriptionsChangedListenerHandler();
+            mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler());
         }
 
         /**
@@ -946,7 +948,7 @@
          * @hide
          */
         public OnSubscriptionsChangedListener(Looper looper) {
-            mHandler = new OnSubscriptionsChangedListenerHandler(looper);
+            mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler(looper));
         }
 
         /**
@@ -958,18 +960,6 @@
             if (DBG) log("onSubscriptionsChanged: NOT OVERRIDDEN");
         }
 
-        /**
-         * The callback methods need to be called on the handler thread where
-         * this object was created.  If the binder did that for us it'd be nice.
-         */
-        IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
-            @Override
-            public void onSubscriptionsChanged() {
-                if (DBG) log("callback: received, sendEmptyMessage(0) to handler");
-                mHandler.sendEmptyMessage(0);
-            }
-        };
-
         private void log(String s) {
             Rlog.d(LOG_TAG, s);
         }
@@ -1011,21 +1001,19 @@
      *                 onSubscriptionsChanged overridden.
      */
     public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
+        if (listener == null) return;
         String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         if (DBG) {
             logd("register OnSubscriptionsChangedListener pkgName=" + pkgName
                     + " listener=" + listener);
         }
-        try {
-            // We use the TelephonyRegistry as it runs in the system and thus is always
-            // available. Where as SubscriptionController could crash and not be available
-            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
-                    "telephony.registry"));
-            if (tr != null) {
-                tr.addOnSubscriptionsChangedListener(pkgName, listener.callback);
-            }
-        } catch (RemoteException ex) {
-            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
+        // We use the TelephonyRegistry as it runs in the system and thus is always
+        // available. Where as SubscriptionController could crash and not be available
+        TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
+                mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+        if (telephonyRegistryManager != null) {
+            telephonyRegistryManager.addOnSubscriptionsChangedListener(listener,
+                    listener.mExecutor);
         }
     }
 
@@ -1037,21 +1025,18 @@
      * @param listener that is to be unregistered.
      */
     public void removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
+        if (listener == null) return;
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         if (DBG) {
             logd("unregister OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug
                     + " listener=" + listener);
         }
-        try {
-            // We use the TelephonyRegistry as it runs in the system and thus is always
-            // available where as SubscriptionController could crash and not be available
-            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
-                    "telephony.registry"));
-            if (tr != null) {
-                tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
-            }
-        } catch (RemoteException ex) {
-            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
+        // We use the TelephonyRegistry as it runs in the system and thus is always
+        // available where as SubscriptionController could crash and not be available
+        TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
+                mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+        if (telephonyRegistryManager != null) {
+            telephonyRegistryManager.removeOnSubscriptionsChangedListener(listener);
         }
     }
 
@@ -1070,7 +1055,6 @@
      * for #onOpportunisticSubscriptionsChanged to be invoked.
      */
     public static class OnOpportunisticSubscriptionsChangedListener {
-        private Executor mExecutor;
         /**
          * Callback invoked when there is any change to any SubscriptionInfo. Typically
          * this method would invoke {@link #getActiveSubscriptionInfoList}
@@ -1079,27 +1063,6 @@
             if (DBG) log("onOpportunisticSubscriptionsChanged: NOT OVERRIDDEN");
         }
 
-        private void setExecutor(Executor executor) {
-            mExecutor = executor;
-        }
-
-        /**
-         * The callback methods need to be called on the handler thread where
-         * this object was created.  If the binder did that for us it'd be nice.
-         */
-        IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
-            @Override
-            public void onSubscriptionsChanged() {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    if (DBG) log("onOpportunisticSubscriptionsChanged callback received.");
-                    mExecutor.execute(() -> onOpportunisticSubscriptionsChanged());
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-            }
-        };
-
         private void log(String s) {
             Rlog.d(LOG_TAG, s);
         }
@@ -1126,18 +1089,13 @@
                     + " listener=" + listener);
         }
 
-        listener.setExecutor(executor);
-
-        try {
-            // We use the TelephonyRegistry as it runs in the system and thus is always
-            // available. Where as SubscriptionController could crash and not be available
-            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
-                    "telephony.registry"));
-            if (tr != null) {
-                tr.addOnOpportunisticSubscriptionsChangedListener(pkgName, listener.callback);
-            }
-        } catch (RemoteException ex) {
-            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
+        // We use the TelephonyRegistry as it runs in the system and thus is always
+        // available where as SubscriptionController could crash and not be available
+        TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
+                mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+        if (telephonyRegistryManager != null) {
+            telephonyRegistryManager.addOnOpportunisticSubscriptionsChangedListener(
+                    listener, executor);
         }
     }
 
@@ -1157,16 +1115,10 @@
             logd("unregister OnOpportunisticSubscriptionsChangedListener pkgForDebug="
                     + pkgForDebug + " listener=" + listener);
         }
-        try {
-            // We use the TelephonyRegistry as it runs in the system and thus is always
-            // available where as SubscriptionController could crash and not be available
-            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
-                    "telephony.registry"));
-            if (tr != null) {
-                tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
-            }
-        } catch (RemoteException ex) {
-            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
+        TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
+                mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+        if (telephonyRegistryManager != null) {
+            telephonyRegistryManager.removeOnOpportunisticSubscriptionsChangedListener(listener);
         }
     }
 
@@ -2420,8 +2372,12 @@
      * @param plans the list of plans. The first plan is always the primary and
      *            most important plan. Any additional plans are secondary and
      *            may not be displayed or used by decision making logic.
+     *            The list of all plans must meet the requirements defined in
+     *            {@link SubscriptionPlan.Builder#setNetworkTypes(int[])}.
      * @throws SecurityException if the caller doesn't meet the requirements
      *             outlined above.
+     * @throws IllegalArgumentException if plans don't meet the requirements
+     *             mentioned above.
      */
     public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
         try {
@@ -2466,51 +2422,10 @@
      */
     public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
             @DurationMillisLong long timeoutMillis) {
-        setSubscriptionOverrideUnmetered(subId, null, overrideUnmetered, timeoutMillis);
-    }
-
-    /**
-     * Temporarily override the billing relationship between a carrier and
-     * a specific subscriber to be considered unmetered for the given network
-     * types. This will be reflected to apps via
-     * {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED}.
-     * This method is only accessible to the following narrow set of apps:
-     * <ul>
-     * <li>The carrier app for this subscriberId, as determined by
-     * {@link TelephonyManager#hasCarrierPrivileges()}.
-     * <li>The carrier app explicitly delegated access through
-     * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
-     * </ul>
-     *
-     * @param subId the subscriber this override applies to.
-     * @param networkTypes all network types to set an override for. A null
-     *            network type means to apply the override to all network types.
-     *            Any unspecified network types will default to metered.
-     * @param overrideUnmetered set if the billing relationship should be
-     *            considered unmetered.
-     * @param timeoutMillis the timeout after which the requested override will
-     *            be automatically cleared, or {@code 0} to leave in the
-     *            requested state until explicitly cleared, or the next reboot,
-     *            whichever happens first.
-     * @throws SecurityException if the caller doesn't meet the requirements
-     *            outlined above.
-     * {@hide}
-     */
-    public void setSubscriptionOverrideUnmetered(int subId,
-            @Nullable @NetworkType int[] networkTypes, boolean overrideUnmetered,
-            @DurationMillisLong long timeoutMillis) {
         try {
-            long networkTypeMask = 0;
-            if (networkTypes != null) {
-                for (int networkType : networkTypes) {
-                    networkTypeMask |= TelephonyManager.getBitMaskForNetworkType(networkType);
-                }
-            } else {
-                networkTypeMask = ~0;
-            }
             final int overrideValue = overrideUnmetered ? OVERRIDE_UNMETERED : 0;
             getNetworkPolicy().setSubscriptionOverride(subId, OVERRIDE_UNMETERED, overrideValue,
-                    networkTypeMask, timeoutMillis, mContext.getOpPackageName());
+                    timeoutMillis, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2542,52 +2457,10 @@
      */
     public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
             @DurationMillisLong long timeoutMillis) {
-        setSubscriptionOverrideCongested(subId, null, overrideCongested, timeoutMillis);
-    }
-
-    /**
-     * Temporarily override the billing relationship plan between a carrier and
-     * a specific subscriber to be considered congested. This will cause the
-     * device to delay certain network requests when possible, such as developer
-     * jobs that are willing to run in a flexible time window.
-     * <p>
-     * This method is only accessible to the following narrow set of apps:
-     * <ul>
-     * <li>The carrier app for this subscriberId, as determined by
-     * {@link TelephonyManager#hasCarrierPrivileges()}.
-     * <li>The carrier app explicitly delegated access through
-     * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
-     * </ul>
-     *
-     * @param subId the subscriber this override applies to.
-     * @param networkTypes all network types to set an override for. A null
-     *            network type means to apply the override to all network types.
-     *            Any unspecified network types will default to not congested.
-     * @param overrideCongested set if the subscription should be considered
-     *            congested.
-     * @param timeoutMillis the timeout after which the requested override will
-     *            be automatically cleared, or {@code 0} to leave in the
-     *            requested state until explicitly cleared, or the next reboot,
-     *            whichever happens first.
-     * @throws SecurityException if the caller doesn't meet the requirements
-     *             outlined above.
-     * @hide
-     */
-    public void setSubscriptionOverrideCongested(int subId,
-            @Nullable @NetworkType int[] networkTypes, boolean overrideCongested,
-            @DurationMillisLong long timeoutMillis) {
         try {
-            long networkTypeMask = 0;
-            if (networkTypes != null) {
-                for (int networkType : networkTypes) {
-                    networkTypeMask |= TelephonyManager.getBitMaskForNetworkType(networkType);
-                }
-            } else {
-                networkTypeMask = ~0;
-            }
             final int overrideValue = overrideCongested ? OVERRIDE_CONGESTED : 0;
             getNetworkPolicy().setSubscriptionOverride(subId, OVERRIDE_CONGESTED, overrideValue,
-                    networkTypeMask, timeoutMillis, mContext.getOpPackageName());
+                    timeoutMillis, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/telephony/java/android/telephony/SubscriptionPlan.java
index ec2050f..e24eb26 100644
--- a/telephony/java/android/telephony/SubscriptionPlan.java
+++ b/telephony/java/android/telephony/SubscriptionPlan.java
@@ -24,6 +24,7 @@
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telephony.Annotation.NetworkType;
 import android.util.Range;
 import android.util.RecurrenceRule;
 
@@ -33,6 +34,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.time.Period;
 import java.time.ZonedDateTime;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.Objects;
 
@@ -80,6 +82,8 @@
     private int dataLimitBehavior = LIMIT_BEHAVIOR_UNKNOWN;
     private long dataUsageBytes = BYTES_UNKNOWN;
     private long dataUsageTime = TIME_UNKNOWN;
+    private @NetworkType int[] networkTypes;
+    private long networkTypesBitMask;
 
     private SubscriptionPlan(RecurrenceRule cycleRule) {
         this.cycleRule = Preconditions.checkNotNull(cycleRule);
@@ -93,6 +97,7 @@
         dataLimitBehavior = source.readInt();
         dataUsageBytes = source.readLong();
         dataUsageTime = source.readLong();
+        networkTypes = source.createIntArray();
     }
 
     @Override
@@ -109,6 +114,7 @@
         dest.writeInt(dataLimitBehavior);
         dest.writeLong(dataUsageBytes);
         dest.writeLong(dataUsageTime);
+        dest.writeIntArray(networkTypes);
     }
 
     @Override
@@ -121,13 +127,14 @@
                 .append(" dataLimitBehavior=").append(dataLimitBehavior)
                 .append(" dataUsageBytes=").append(dataUsageBytes)
                 .append(" dataUsageTime=").append(dataUsageTime)
+                .append(" networkTypes=").append(Arrays.toString(networkTypes))
                 .append("}").toString();
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(cycleRule, title, summary, dataLimitBytes, dataLimitBehavior,
-                dataUsageBytes, dataUsageTime);
+                dataUsageBytes, dataUsageTime, Arrays.hashCode(networkTypes));
     }
 
     @Override
@@ -140,7 +147,8 @@
                     && dataLimitBytes == other.dataLimitBytes
                     && dataLimitBehavior == other.dataLimitBehavior
                     && dataUsageBytes == other.dataUsageBytes
-                    && dataUsageTime == other.dataUsageTime;
+                    && dataUsageTime == other.dataUsageTime
+                    && Arrays.equals(networkTypes, other.networkTypes);
         }
         return false;
     }
@@ -204,6 +212,32 @@
     }
 
     /**
+     * Return an array containing all {@link NetworkType}s this SubscriptionPlan applies to.
+     * A null array means this SubscriptionPlan applies to all network types.
+     */
+    public @Nullable @NetworkType int[] getNetworkTypes() {
+        return networkTypes;
+    }
+
+    /**
+     * Return the networkTypes array converted to a {@link TelephonyManager.NetworkTypeBitMask}
+     * @hide
+     */
+    public long getNetworkTypesBitMask() {
+        // calculate bitmask the first time and save for future calls
+        if (networkTypesBitMask == 0) {
+            if (networkTypes == null) {
+                networkTypesBitMask = ~0;
+            } else {
+                for (int networkType : networkTypes) {
+                    networkTypesBitMask |= TelephonyManager.getBitMaskForNetworkType(networkType);
+                }
+            }
+        }
+        return networkTypesBitMask;
+    }
+
+    /**
      * Return an iterator that will return all valid data usage cycles based on
      * any recurrence rules. The iterator starts from the currently active cycle
      * and walks backwards through time.
@@ -335,5 +369,24 @@
             plan.dataUsageTime = dataUsageTime;
             return this;
         }
+
+        /**
+         * Set the network types this SubscriptionPlan applies to.
+         * The developer must supply at least one plan that applies to all network types (default),
+         * and all additional plans may not include a particular network type more than once.
+         * Plan selection will prefer plans that have specific network types defined
+         * over plans that apply to all network types.
+         *
+         * @param networkTypes a set of all {@link NetworkType}s that apply to this plan.
+         *            A null value or empty array means the plan applies to all network types.
+         */
+        public @NonNull Builder setNetworkTypes(@Nullable @NetworkType int[] networkTypes) {
+            if (networkTypes == null || networkTypes.length == 0) {
+                plan.networkTypes = null;
+            } else {
+                plan.networkTypes = networkTypes;
+            }
+            return this;
+        }
     }
 }
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index 1e0d9a78..10251d7 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -885,6 +885,12 @@
      */
     public static final int CODE_WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION = 1623;
 
+    /**
+     * The dialed RTT call should be retried without RTT
+     * @hide
+     */
+    public static final int CODE_RETRY_ON_IMS_WITHOUT_RTT = 3001;
+
     /*
      * OEM specific error codes. To be used by OEMs when they don't want to reveal error code which
      * would be replaced by ERROR_UNSPECIFIED.
@@ -1065,6 +1071,7 @@
             CODE_REJECT_VT_AVPF_NOT_ALLOWED,
             CODE_REJECT_ONGOING_ENCRYPTED_CALL,
             CODE_REJECT_ONGOING_CS_CALL,
+            CODE_RETRY_ON_IMS_WITHOUT_RTT,
             CODE_OEM_CAUSE_1,
             CODE_OEM_CAUSE_2,
             CODE_OEM_CAUSE_3,
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 668a6af..9e786ce 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -111,7 +111,7 @@
     public static final int EVENT_DATA_SERVICE_BINDING_CHANGED = BASE + 49;
     public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 50;
     public static final int EVENT_DATA_ENABLED_OVERRIDE_RULES_CHANGED = BASE + 51;
-    public static final int EVENT_5G_NETWORK_CHANGED = BASE + 52;
+    public static final int EVENT_SERVICE_STATE_CHANGED = BASE + 52;
     public static final int EVENT_5G_TIMER_HYSTERESIS = BASE + 53;
     public static final int EVENT_5G_TIMER_WATCHDOG = BASE + 54;
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index fd7ec56..39e00cc 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2063,4 +2063,9 @@
      * data might be disabled on non-default data subscription but explicitly turned on by settings.
      */
     boolean isDataAllowedInVoiceCall(int subId);
+
+    /**
+     * Command line command to enable or disable handling of CEP data for test purposes.
+     */
+    oneway void setCepEnabled(boolean isCepEnabled);
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 4654437..b357fa4 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -900,6 +900,20 @@
     }
 
     /**
+     * @return the bearer data byte array
+     */
+    public byte[] getEnvelopeBearerData() {
+        return mEnvelope.bearerData;
+    }
+
+    /**
+     * @return the 16-bit CDMA SCPT service category
+     */
+    public @CdmaSmsCbProgramData.Category int getEnvelopeServiceCategory() {
+        return mEnvelope.serviceCategory;
+    }
+
+    /**
      * {@inheritDoc}
      */
     @Override
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
index 2787b24..c924ab3 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
@@ -57,17 +57,17 @@
 
     // CMAS alert service category assignments, see 3GPP2 C.R1001 table 9.3.3-1
     public static final int SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT  =
-            CdmaSmsCbProgramData.CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT;
+            CdmaSmsCbProgramData.CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT;  // = 4096
     public static final int SERVICE_CATEGORY_CMAS_EXTREME_THREAT            =
-            CdmaSmsCbProgramData.CATEGORY_CMAS_EXTREME_THREAT;
+            CdmaSmsCbProgramData.CATEGORY_CMAS_EXTREME_THREAT;            // = 4097
     public static final int SERVICE_CATEGORY_CMAS_SEVERE_THREAT             =
-            CdmaSmsCbProgramData.CATEGORY_CMAS_SEVERE_THREAT;
+            CdmaSmsCbProgramData.CATEGORY_CMAS_SEVERE_THREAT;             // = 4098
     public static final int SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY =
-            CdmaSmsCbProgramData.CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY;
+            CdmaSmsCbProgramData.CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY; // = 4099
     public static final int SERVICE_CATEGORY_CMAS_TEST_MESSAGE              =
-            CdmaSmsCbProgramData.CATEGORY_CMAS_TEST_MESSAGE;
+            CdmaSmsCbProgramData.CATEGORY_CMAS_TEST_MESSAGE;              // = 4100
     public static final int SERVICE_CATEGORY_CMAS_LAST_RESERVED_VALUE       =
-            CdmaSmsCbProgramData.CATEGORY_CMAS_LAST_RESERVED_VALUE;
+            CdmaSmsCbProgramData.CATEGORY_CMAS_LAST_RESERVED_VALUE;       // = 4351
 
     /**
      * Provides the type of a SMS message like point to point, broadcast or acknowledge
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index fcd4701..5053cee 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -758,7 +758,7 @@
 
     /** {@hide} */
     @Override
-    public Context createContextAsUser(UserHandle user) {
+    public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) {
         throw new UnsupportedOperationException();
     }
 
diff --git a/tests/ApkVerityTest/block_device_writer/block_device_writer.cpp b/tests/ApkVerityTest/block_device_writer/block_device_writer.cpp
index b0c7251..02dfd73 100644
--- a/tests/ApkVerityTest/block_device_writer/block_device_writer.cpp
+++ b/tests/ApkVerityTest/block_device_writer/block_device_writer.cpp
@@ -42,6 +42,42 @@
 //  https://www.kernel.org/doc/Documentation/filesystems/fiemap.txt
 //  https://git.kernel.org/pub/scm/fs/xfs/xfsprogs-dev.git/tree/io/fiemap.c
 
+#ifndef F2FS_IOC_SET_PIN_FILE
+#ifndef F2FS_IOCTL_MAGIC
+#define F2FS_IOCTL_MAGIC 0xf5
+#endif
+#define F2FS_IOC_SET_PIN_FILE _IOW(F2FS_IOCTL_MAGIC, 13, __u32)
+#define F2FS_IOC_GET_PIN_FILE _IOR(F2FS_IOCTL_MAGIC, 14, __u32)
+#endif
+
+struct Args {
+  const char* block_device;
+  const char* file_name;
+  uint64_t byte_offset;
+  bool use_f2fs_pinning;
+};
+
+class ScopedF2fsFilePinning {
+ public:
+  explicit ScopedF2fsFilePinning(const char* file_path) {
+    fd_.reset(TEMP_FAILURE_RETRY(open(file_path, O_WRONLY | O_CLOEXEC, 0)));
+    if (fd_.get() == -1) {
+      perror("Failed to open");
+      return;
+    }
+    __u32 set = 1;
+    ioctl(fd_.get(), F2FS_IOC_SET_PIN_FILE, &set);
+  }
+
+  ~ScopedF2fsFilePinning() {
+    __u32 set = 0;
+    ioctl(fd_.get(), F2FS_IOC_SET_PIN_FILE, &set);
+  }
+
+ private:
+  android::base::unique_fd fd_;
+};
+
 ssize_t get_logical_block_size(const char* block_device) {
   android::base::unique_fd fd(open(block_device, O_RDONLY));
   if (fd.get() < 0) {
@@ -138,28 +174,51 @@
   return 0;
 }
 
-int main(int argc, const char** argv) {
-  if (argc != 4) {
+std::unique_ptr<Args> parse_args(int argc, const char** argv) {
+  if (argc != 4 && argc != 5) {
     fprintf(stderr,
-            "Usage: %s block_dev filename byte_offset\n"
+            "Usage: %s [--use-f2fs-pinning] block_dev filename byte_offset\n"
             "\n"
             "This program bypasses filesystem and damages the specified byte\n"
             "at the physical position on <block_dev> corresponding to the\n"
             "logical byte location in <filename>.\n",
             argv[0]);
+    return nullptr;
+  }
+
+  auto args = std::make_unique<Args>();
+  const char** arg = &argv[1];
+  args->use_f2fs_pinning = strcmp(*arg, "--use-f2fs-pinning") == 0;
+  if (args->use_f2fs_pinning) {
+    ++arg;
+  }
+  args->block_device = *(arg++);
+  args->file_name = *(arg++);
+  args->byte_offset = strtoull(*arg, nullptr, 10);
+  if (args->byte_offset == ULLONG_MAX) {
+    perror("Invalid byte offset");
+    return nullptr;
+  }
+  return args;
+}
+
+int main(int argc, const char** argv) {
+  std::unique_ptr<Args> args = parse_args(argc, argv);
+  if (args == nullptr) {
     return -1;
   }
 
-  const char* block_device = argv[1];
-  const char* file_name = argv[2];
-  uint64_t byte_offset = strtoull(argv[3], nullptr, 10);
-
-  ssize_t block_size = get_logical_block_size(block_device);
+  ssize_t block_size = get_logical_block_size(args->block_device);
   if (block_size < 0) {
     return -1;
   }
 
-  int64_t physical_offset_signed = get_physical_offset(file_name, byte_offset);
+  std::unique_ptr<ScopedF2fsFilePinning> pinned_file;
+  if (args->use_f2fs_pinning) {
+    pinned_file = std::make_unique<ScopedF2fsFilePinning>(args->file_name);
+  }
+
+  int64_t physical_offset_signed = get_physical_offset(args->file_name, args->byte_offset);
   if (physical_offset_signed < 0) {
     return -1;
   }
@@ -172,7 +231,7 @@
   std::unique_ptr<char> buf(static_cast<char*>(
       aligned_alloc(block_size /* alignment */, block_size /* size */)));
 
-  if (read_block_from_device(block_device, physical_block_offset, block_size,
+  if (read_block_from_device(args->block_device, physical_block_offset, block_size,
                              buf.get()) < 0) {
     return -1;
   }
@@ -180,7 +239,7 @@
   printf("before: %hhx\n", *p);
   *p ^= 0xff;
   printf("after: %hhx\n", *p);
-  if (write_block_to_device(block_device, physical_block_offset, block_size,
+  if (write_block_to_device(args->block_device, physical_block_offset, block_size,
                             buf.get()) < 0) {
     return -1;
   }
diff --git a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java b/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
index 761c5ce..2445a6a 100644
--- a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
+++ b/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
@@ -38,6 +38,7 @@
 import org.junit.runner.RunWith;
 
 import java.io.FileNotFoundException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 
@@ -440,8 +441,15 @@
             throws DeviceNotAvailableException {
         assertTrue(path.startsWith("/data/"));
         ITestDevice.MountPointInfo mountPoint = mDevice.getMountPointInfo("/data");
-        expectRemoteCommandToSucceed(String.join(" ", DAMAGING_EXECUTABLE,
-                    mountPoint.filesystem, path, Long.toString(offsetOfTargetingByte)));
+        ArrayList<String> args = new ArrayList<>();
+        args.add(DAMAGING_EXECUTABLE);
+        if ("f2fs".equals(mountPoint.type)) {
+            args.add("--use-f2fs-pinning");
+        }
+        args.add(mountPoint.filesystem);
+        args.add(path);
+        args.add(Long.toString(offsetOfTargetingByte));
+        expectRemoteCommandToSucceed(String.join(" ", args));
     }
 
     private String getApkPath(String packageName) throws DeviceNotAvailableException {
diff --git a/tests/Codegen/runTest.sh b/tests/Codegen/runTest.sh
index 0e90dea..929f122 100755
--- a/tests/Codegen/runTest.sh
+++ b/tests/Codegen/runTest.sh
@@ -17,11 +17,13 @@
         header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java && \
         header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java && \
         header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java && \
-        cd $ANDROID_BUILD_TOP &&
-        header_and_eval mmma -j16 frameworks/base/tests/Codegen && \
-        header_and_eval adb install -r -t "$(find $ANDROID_TARGET_OUT_TESTCASES -name 'CodegenTests.apk')" && \
-        # header_and_eval adb shell am set-debug-app -w com.android.codegentest && \
-        header_and_eval adb shell am instrument -w -e package com.android.codegentest com.android.codegentest/androidx.test.runner.AndroidJUnitRunner
+        (
+            cd $ANDROID_BUILD_TOP &&
+            header_and_eval mmma -j16 frameworks/base/tests/Codegen && \
+            header_and_eval adb install -r -t "$(find $ANDROID_TARGET_OUT_TESTCASES -name 'CodegenTests.apk')" && \
+            # header_and_eval adb shell am set-debug-app -w com.android.codegentest && \
+            header_and_eval adb shell am instrument -w -e package com.android.codegentest com.android.codegentest/androidx.test.runner.AndroidJUnitRunner
+        )
 
         exitCode=$?
 
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
index 10eba6a..325c1c0 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
@@ -32,13 +32,17 @@
 
 
 
-    // Code below generated by codegen v1.0.7.
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
     // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
 
 
     @DataClass.Generated.Member
@@ -54,7 +58,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(android.os.Parcel dest, int flags) {
+    public void writeToParcel(@android.annotation.NonNull android.os.Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
@@ -68,7 +72,7 @@
     /** @hide */
     @SuppressWarnings({"unchecked", "RedundantCast"})
     @DataClass.Generated.Member
-    protected HierrarchicalDataClassBase(android.os.Parcel in) {
+    protected HierrarchicalDataClassBase(@android.annotation.NonNull android.os.Parcel in) {
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
@@ -88,14 +92,14 @@
         }
 
         @Override
-        public HierrarchicalDataClassBase createFromParcel(android.os.Parcel in) {
+        public HierrarchicalDataClassBase createFromParcel(@android.annotation.NonNull android.os.Parcel in) {
             return new HierrarchicalDataClassBase(in);
         }
     };
 
     @DataClass.Generated(
-            time = 1570576455287L,
-            codegenVersion = "1.0.7",
+            time = 1571258914826L,
+            codegenVersion = "1.0.9",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java",
             inputSignatures = "private  int mBaseData\nclass HierrarchicalDataClassBase extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genSetters=true)")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
index 1085a6a..6c92009 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
@@ -46,13 +46,17 @@
 
 
 
-    // Code below generated by codegen v1.0.7.
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
     // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
 
 
     @DataClass.Generated.Member
@@ -70,7 +74,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(android.os.Parcel dest, int flags) {
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
@@ -86,7 +90,7 @@
     /** @hide */
     @SuppressWarnings({"unchecked", "RedundantCast"})
     @DataClass.Generated.Member
-    protected HierrarchicalDataClassChild(android.os.Parcel in) {
+    protected HierrarchicalDataClassChild(@NonNull android.os.Parcel in) {
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
@@ -110,14 +114,14 @@
         }
 
         @Override
-        public HierrarchicalDataClassChild createFromParcel(android.os.Parcel in) {
+        public HierrarchicalDataClassChild createFromParcel(@NonNull android.os.Parcel in) {
             return new HierrarchicalDataClassChild(in);
         }
     };
 
     @DataClass.Generated(
-            time = 1570576456245L,
-            codegenVersion = "1.0.7",
+            time = 1571258915848L,
+            codegenVersion = "1.0.9",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java",
             inputSignatures = "private @android.annotation.NonNull java.lang.String mChildData\nclass HierrarchicalDataClassChild extends com.android.codegentest.HierrarchicalDataClassBase implements []\n@com.android.internal.util.DataClass(genParcelable=true, genConstructor=false, genSetters=true)")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
index 75ef963..36def8a 100644
--- a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
@@ -16,6 +16,7 @@
 package com.android.codegentest;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseArray;
@@ -46,15 +47,22 @@
     @NonNull SparseArray<SampleWithCustomBuilder> mSparseArray = null;
     @NonNull SparseIntArray mSparseIntArray = null;
 
+    @SuppressWarnings({"WeakerAccess"})
+    @Nullable Boolean mNullableBoolean = null;
 
 
-    // Code below generated by codegen v1.0.7.
+
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
     // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
 
 
     @DataClass.Generated.Member
@@ -65,7 +73,8 @@
             @NonNull Map<String,SampleWithCustomBuilder> map,
             @NonNull Map<String,String> stringMap,
             @NonNull SparseArray<SampleWithCustomBuilder> sparseArray,
-            @NonNull SparseIntArray sparseIntArray) {
+            @NonNull SparseIntArray sparseIntArray,
+            @SuppressWarnings({ "WeakerAccess" }) @Nullable Boolean nullableBoolean) {
         this.mStringArray = stringArray;
         AnnotationValidations.validate(
                 NonNull.class, null, mStringArray);
@@ -87,6 +96,7 @@
         this.mSparseIntArray = sparseIntArray;
         AnnotationValidations.validate(
                 NonNull.class, null, mSparseIntArray);
+        this.mNullableBoolean = nullableBoolean;
 
         // onConstructed(); // You can define this method to get a callback
     }
@@ -126,6 +136,11 @@
         return mSparseIntArray;
     }
 
+    @DataClass.Generated.Member
+    public @SuppressWarnings({ "WeakerAccess" }) @Nullable Boolean getNullableBoolean() {
+        return mNullableBoolean;
+    }
+
     @Override
     @DataClass.Generated.Member
     public String toString() {
@@ -139,16 +154,20 @@
                 "map = " + mMap + ", " +
                 "stringMap = " + mStringMap + ", " +
                 "sparseArray = " + mSparseArray + ", " +
-                "sparseIntArray = " + mSparseIntArray +
+                "sparseIntArray = " + mSparseIntArray + ", " +
+                "nullableBoolean = " + mNullableBoolean +
         " }";
     }
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
+        int flg = 0;
+        if (mNullableBoolean != null) flg |= 0x80;
+        dest.writeInt(flg);
         dest.writeStringArray(mStringArray);
         dest.writeIntArray(mIntArray);
         dest.writeStringList(mStringList);
@@ -156,6 +175,7 @@
         dest.writeMap(mStringMap);
         dest.writeSparseArray(mSparseArray);
         dest.writeSparseIntArray(mSparseIntArray);
+        if (mNullableBoolean != null) dest.writeBoolean(mNullableBoolean);
     }
 
     @Override
@@ -165,10 +185,11 @@
     /** @hide */
     @SuppressWarnings({"unchecked", "RedundantCast"})
     @DataClass.Generated.Member
-    protected ParcelAllTheThingsDataClass(Parcel in) {
+    protected ParcelAllTheThingsDataClass(@NonNull Parcel in) {
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
+        int flg = in.readInt();
         String[] stringArray = in.createStringArray();
         int[] intArray = in.createIntArray();
         List<String> stringList = new java.util.ArrayList<>();
@@ -179,6 +200,7 @@
         in.readMap(stringMap, String.class.getClassLoader());
         SparseArray<SampleWithCustomBuilder> sparseArray = (SparseArray) in.readSparseArray(SampleWithCustomBuilder.class.getClassLoader());
         SparseIntArray sparseIntArray = (SparseIntArray) in.readSparseIntArray();
+        Boolean nullableBoolean = (flg & 0x80) == 0 ? null : (Boolean) in.readBoolean();
 
         this.mStringArray = stringArray;
         AnnotationValidations.validate(
@@ -201,6 +223,7 @@
         this.mSparseIntArray = sparseIntArray;
         AnnotationValidations.validate(
                 NonNull.class, null, mSparseIntArray);
+        this.mNullableBoolean = nullableBoolean;
 
         // onConstructed(); // You can define this method to get a callback
     }
@@ -214,7 +237,7 @@
         }
 
         @Override
-        public ParcelAllTheThingsDataClass createFromParcel(Parcel in) {
+        public ParcelAllTheThingsDataClass createFromParcel(@NonNull Parcel in) {
             return new ParcelAllTheThingsDataClass(in);
         }
     };
@@ -233,6 +256,7 @@
         private @NonNull Map<String,String> mStringMap;
         private @NonNull SparseArray<SampleWithCustomBuilder> mSparseArray;
         private @NonNull SparseIntArray mSparseIntArray;
+        private @SuppressWarnings({ "WeakerAccess" }) @Nullable Boolean mNullableBoolean;
 
         private long mBuilderFieldsSet = 0L;
 
@@ -328,10 +352,18 @@
             return this;
         }
 
+        @DataClass.Generated.Member
+        public @NonNull Builder setNullableBoolean(@SuppressWarnings({ "WeakerAccess" }) @Nullable Boolean value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x80;
+            mNullableBoolean = value;
+            return this;
+        }
+
         /** Builds the instance. This builder should not be touched after calling this! */
         public ParcelAllTheThingsDataClass build() {
             checkNotUsed();
-            mBuilderFieldsSet |= 0x80; // Mark builder used
+            mBuilderFieldsSet |= 0x100; // Mark builder used
 
             if ((mBuilderFieldsSet & 0x1) == 0) {
                 mStringArray = null;
@@ -354,6 +386,9 @@
             if ((mBuilderFieldsSet & 0x40) == 0) {
                 mSparseIntArray = null;
             }
+            if ((mBuilderFieldsSet & 0x80) == 0) {
+                mNullableBoolean = null;
+            }
             ParcelAllTheThingsDataClass o = new ParcelAllTheThingsDataClass(
                     mStringArray,
                     mIntArray,
@@ -361,12 +396,13 @@
                     mMap,
                     mStringMap,
                     mSparseArray,
-                    mSparseIntArray);
+                    mSparseIntArray,
+                    mNullableBoolean);
             return o;
         }
 
         private void checkNotUsed() {
-            if ((mBuilderFieldsSet & 0x80) != 0) {
+            if ((mBuilderFieldsSet & 0x100) != 0) {
                 throw new IllegalStateException(
                         "This Builder should not be reused. Use a new Builder instance instead");
             }
@@ -374,10 +410,10 @@
     }
 
     @DataClass.Generated(
-            time = 1570576454326L,
-            codegenVersion = "1.0.7",
+            time = 1571258913802L,
+            codegenVersion = "1.0.9",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java",
-            inputSignatures = " @android.annotation.NonNull java.lang.String[] mStringArray\n @android.annotation.NonNull int[] mIntArray\n @android.annotation.NonNull java.util.List<java.lang.String> mStringList\n @android.annotation.NonNull java.util.Map<java.lang.String,com.android.codegentest.SampleWithCustomBuilder> mMap\n @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.String> mStringMap\n @android.annotation.NonNull android.util.SparseArray<com.android.codegentest.SampleWithCustomBuilder> mSparseArray\n @android.annotation.NonNull android.util.SparseIntArray mSparseIntArray\nclass ParcelAllTheThingsDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)")
+            inputSignatures = " @android.annotation.NonNull java.lang.String[] mStringArray\n @android.annotation.NonNull int[] mIntArray\n @android.annotation.NonNull java.util.List<java.lang.String> mStringList\n @android.annotation.NonNull java.util.Map<java.lang.String,com.android.codegentest.SampleWithCustomBuilder> mMap\n @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.String> mStringMap\n @android.annotation.NonNull android.util.SparseArray<com.android.codegentest.SampleWithCustomBuilder> mSparseArray\n @android.annotation.NonNull android.util.SparseIntArray mSparseIntArray\n @java.lang.SuppressWarnings({\"WeakerAccess\"}) @android.annotation.Nullable java.lang.Boolean mNullableBoolean\nclass ParcelAllTheThingsDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
index 14010a9..c444d61 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
@@ -342,13 +342,17 @@
 
 
 
-    // Code below generated by codegen v1.0.7.
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
     // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
 
 
     @IntDef(prefix = "STATE_", value = {
@@ -1115,7 +1119,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public boolean equals(Object o) {
+    public boolean equals(@Nullable Object o) {
         // You can override field equality logic by defining either of the methods like:
         // boolean fieldNameEquals(SampleDataClass other) { ... }
         // boolean fieldNameEquals(FieldType otherValue) { ... }
@@ -1180,8 +1184,8 @@
 
     @DataClass.Generated.Member
     void forEachField(
-            DataClass.PerIntFieldAction<SampleDataClass> actionInt,
-            DataClass.PerObjectFieldAction<SampleDataClass> actionObject) {
+            @NonNull DataClass.PerIntFieldAction<SampleDataClass> actionInt,
+            @NonNull DataClass.PerObjectFieldAction<SampleDataClass> actionObject) {
         actionInt.acceptInt(this, "num", mNum);
         actionInt.acceptInt(this, "num2", mNum2);
         actionInt.acceptInt(this, "num4", mNum4);
@@ -1207,7 +1211,7 @@
     /** @deprecated May cause boxing allocations - use with caution! */
     @Deprecated
     @DataClass.Generated.Member
-    void forEachField(DataClass.PerObjectFieldAction<SampleDataClass> action) {
+    void forEachField(@NonNull DataClass.PerObjectFieldAction<SampleDataClass> action) {
         action.acceptObject(this, "num", mNum);
         action.acceptObject(this, "num2", mNum2);
         action.acceptObject(this, "num4", mNum4);
@@ -1254,7 +1258,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
@@ -1293,7 +1297,7 @@
     /** @hide */
     @SuppressWarnings({"unchecked", "RedundantCast"})
     @DataClass.Generated.Member
-    /* package-private */ SampleDataClass(Parcel in) {
+    /* package-private */ SampleDataClass(@NonNull Parcel in) {
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
@@ -1416,7 +1420,7 @@
         }
 
         @Override
-        public SampleDataClass createFromParcel(Parcel in) {
+        public SampleDataClass createFromParcel(@NonNull Parcel in) {
             return new SampleDataClass(in);
         }
     };
@@ -1868,8 +1872,8 @@
     }
 
     @DataClass.Generated(
-            time = 1570576452225L,
-            codegenVersion = "1.0.7",
+            time = 1571258911688L,
+            codegenVersion = "1.0.9",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java",
             inputSignatures = "public static final  java.lang.String STATE_NAME_UNDEFINED\npublic static final  java.lang.String STATE_NAME_ON\npublic static final  java.lang.String STATE_NAME_OFF\npublic static final  int STATE_UNDEFINED\npublic static final  int STATE_ON\npublic static final  int STATE_OFF\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_AUGMENTED_REQUEST\nprivate  int mNum\nprivate  int mNum2\nprivate  int mNum4\nprivate @android.annotation.Nullable java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mName2\nprivate @android.annotation.NonNull java.lang.String mName4\nprivate @android.annotation.Nullable android.view.accessibility.AccessibilityNodeInfo mOtherParcelable\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.codegentest.MyDateParcelling.class) @android.annotation.NonNull java.util.Date mDate\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForPattern.class) @android.annotation.NonNull java.util.regex.Pattern mPattern\nprivate @android.annotation.NonNull java.util.List<android.net.LinkAddress> mLinkAddresses2\nprivate @com.android.internal.util.DataClass.PluralOf(\"linkAddress\") @android.annotation.NonNull java.util.ArrayList<android.net.LinkAddress> mLinkAddresses\nprivate @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses4\nprivate @com.android.codegentest.SampleDataClass.StateName @android.annotation.NonNull java.lang.String mStateName\nprivate @com.android.codegentest.SampleDataClass.RequestFlags int mFlags\nprivate @com.android.codegentest.SampleDataClass.State int mState\npublic @android.annotation.NonNull java.lang.CharSequence charSeq\nprivate final @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses5\nprivate transient  android.net.LinkAddress[] mLinkAddresses6\ntransient  int[] mTmpStorage\nprivate @android.annotation.StringRes int mStringRes\nprivate @android.annotation.IntRange(from=0L, to=6L) int mDayOfWeek\nprivate @android.annotation.Size(2L) @android.annotation.NonNull @com.android.internal.util.DataClass.Each @android.annotation.FloatRange(from=0.0) float[] mCoords\nprivate static  java.lang.String defaultName4()\nprivate  int[] lazyInitTmpStorage()\npublic  android.net.LinkAddress[] getLinkAddresses4()\nprivate  boolean patternEquals(java.util.regex.Pattern)\nprivate  int patternHashCode()\nprivate  void onConstructed()\npublic  void dump(java.io.PrintWriter)\nclass SampleDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=true, genEqualsHashCode=true, genToString=true, genForEachField=true, genSetters=true)")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
index b5f6c73..55feae7 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
@@ -85,13 +85,17 @@
 
 
 
-    // Code below generated by codegen v1.0.7.
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
     // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
 
 
     @DataClass.Generated.Member
@@ -138,7 +142,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
@@ -154,7 +158,7 @@
     /** @hide */
     @SuppressWarnings({"unchecked", "RedundantCast"})
     @DataClass.Generated.Member
-    protected SampleWithCustomBuilder(Parcel in) {
+    protected SampleWithCustomBuilder(@NonNull Parcel in) {
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
@@ -180,7 +184,7 @@
         }
 
         @Override
-        public SampleWithCustomBuilder createFromParcel(Parcel in) {
+        public SampleWithCustomBuilder createFromParcel(@NonNull Parcel in) {
             return new SampleWithCustomBuilder(in);
         }
     };
@@ -249,8 +253,8 @@
     }
 
     @DataClass.Generated(
-            time = 1570576453295L,
-            codegenVersion = "1.0.7",
+            time = 1571258912752L,
+            codegenVersion = "1.0.9",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java",
             inputSignatures = "  long delayAmount\n @android.annotation.NonNull java.util.concurrent.TimeUnit delayUnit\n  long creationTimestamp\nprivate static  java.util.concurrent.TimeUnit unparcelDelayUnit(android.os.Parcel)\nprivate  void parcelDelayUnit(android.os.Parcel,int)\nclass SampleWithCustomBuilder extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)\nabstract  com.android.codegentest.SampleWithCustomBuilder.Builder setDelayAmount(long)\npublic abstract  com.android.codegentest.SampleWithCustomBuilder.Builder setDelayUnit(java.util.concurrent.TimeUnit)\npublic  com.android.codegentest.SampleWithCustomBuilder.Builder setDelay(long,java.util.concurrent.TimeUnit)\nclass BaseBuilder extends java.lang.Object implements []")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
index 0ce8aba..b967f19 100644
--- a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
+++ b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
@@ -51,18 +51,22 @@
 
 
 
-    // Code below generated by codegen v1.0.7.
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
     // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
 
 
     @DataClass.Generated(
-            time = 1570576457249L,
-            codegenVersion = "1.0.7",
+            time = 1571258916868L,
+            codegenVersion = "1.0.9",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java",
             inputSignatures = "public @android.annotation.NonNull java.lang.String someMethod(int)\nclass StaleDataclassDetectorFalsePositivesTest extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=false)")
     @Deprecated
diff --git a/tests/FlickerTests/TEST_MAPPING b/tests/FlickerTests/TEST_MAPPING
index 55a6147..f34c432 100644
--- a/tests/FlickerTests/TEST_MAPPING
+++ b/tests/FlickerTests/TEST_MAPPING
@@ -1,7 +1,8 @@
 {
   "postsubmit": [
     {
-      "name": "FlickerTests"
+      "name": "FlickerTests",
+      "keywords": ["primary-device"]
     }
   ]
 }
\ No newline at end of file
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index 231d045b..085c53c 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -19,7 +19,6 @@
     static_libs: ["androidx.test.rules", "cts-rollback-lib", "cts-install-lib"],
     test_suites: ["general-tests"],
     test_config: "RollbackTest.xml",
-    // TODO: sdk_version: "test_current" when Intent#resolveSystemservice is TestApi
 }
 
 java_test_host {
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index ed8f272..599ee56 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -33,6 +33,7 @@
 import android.content.IntentFilter;
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
+import android.os.UserManager;
 import android.provider.DeviceConfig;
 import android.util.Log;
 
@@ -52,7 +53,9 @@
 import org.junit.runners.JUnit4;
 
 import java.util.Collections;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /**
  * Test system Rollback APIs.
@@ -96,7 +99,10 @@
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
                     Manifest.permission.TEST_MANAGE_ROLLBACKS,
-                    Manifest.permission.MANAGE_ROLLBACKS);
+                    Manifest.permission.MANAGE_ROLLBACKS,
+                    Manifest.permission.MANAGE_USERS,
+                    Manifest.permission.CREATE_USERS,
+                    Manifest.permission.INTERACT_ACROSS_USERS);
 
             // Register a broadcast receiver for notification when the
             // rollback has been committed.
@@ -106,7 +112,6 @@
             // Uninstall TestApp.A
             Uninstall.packages(TestApp.A);
             assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
-
             // TODO: There is currently a race condition between when the app is
             // uninstalled and when rollback manager deletes the rollback. Fix it
             // so that's not the case!
@@ -149,6 +154,12 @@
             RollbackUtils.rollback(available.getRollbackId());
             assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
 
+            UserManager um = (UserManager) context.getSystemService(context.USER_SERVICE);
+            List<Integer> userIds = um.getUsers(true)
+                    .stream().map(user -> user.id).collect(Collectors.toList());
+            assertThat(InstallUtils.isOnlyInstalledForUser(TestApp.A,
+                    context.getUserId(), userIds)).isTrue();
+
             // Verify we received a broadcast for the rollback.
             // TODO: Race condition between the timeout and when the broadcast is
             // received could lead to test flakiness.
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index 9e6ac8e..95fe61d 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -92,7 +92,7 @@
      * Enable rollback phase.
      */
     @Test
-    public void testBadApkOnlyEnableRollback() throws Exception {
+    public void testBadApkOnly_Phase1() throws Exception {
         Uninstall.packages(TestApp.A);
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
 
@@ -101,9 +101,6 @@
         InstallUtils.processUserData(TestApp.A);
 
         Install.single(TestApp.ACrashing2).setEnableRollback().setStaged().commit();
-
-        // At this point, the host test driver will reboot the device and run
-        // testBadApkOnlyConfirmEnableRollback().
     }
 
     /**
@@ -111,7 +108,7 @@
      * Confirm that rollback was successfully enabled.
      */
     @Test
-    public void testBadApkOnlyConfirmEnableRollback() throws Exception {
+    public void testBadApkOnly_Phase2() throws Exception {
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
         InstallUtils.processUserData(TestApp.A);
 
@@ -122,9 +119,6 @@
         assertThat(rollback).packagesContainsExactly(
                 Rollback.from(TestApp.A2).to(TestApp.A1));
         assertThat(rollback.isStaged()).isTrue();
-
-        // At this point, the host test driver will run
-        // testBadApkOnlyTriggerRollback().
     }
 
     /**
@@ -133,15 +127,14 @@
      * rebooting the test out from under it.
      */
     @Test
-    public void testBadApkOnlyTriggerRollback() throws Exception {
+    public void testBadApkOnly_Phase3() throws Exception {
         // Crash TestApp.A PackageWatchdog#TRIGGER_FAILURE_COUNT times to trigger rollback
         RollbackUtils.sendCrashBroadcast(TestApp.A, 5);
 
-        // We expect the device to be rebooted automatically. Wait for that to
-        // happen. At that point, the host test driver will wait for the
-        // device to come back up and run testApkOnlyConfirmRollback().
+        // We expect the device to be rebooted automatically. Wait for that to happen.
         Thread.sleep(30 * 1000);
 
+        // Raise an error anyway if reboot didn't happen.
         fail("watchdog did not trigger reboot");
     }
 
@@ -150,7 +143,7 @@
      * Confirm rollback phase.
      */
     @Test
-    public void testBadApkOnlyConfirmRollback() throws Exception {
+    public void testBadApkOnly_Phase4() throws Exception {
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
         InstallUtils.processUserData(TestApp.A);
 
@@ -177,8 +170,11 @@
                         networkStack)).isNull();
     }
 
+    /**
+     * Stage install ModuleMetadata package to simulate a Mainline module update.
+     */
     @Test
-    public void installModuleMetadataPackage() throws Exception {
+    public void testNativeWatchdogTriggersRollback_Phase1() throws Exception {
         resetModuleMetadataPackage();
         Context context = InstrumentationRegistry.getContext();
         PackageInfo metadataPackageInfo = context.getPackageManager().getPackageInfo(
@@ -192,6 +188,46 @@
                 + metadataApkPath);
     }
 
+    /**
+     * Verify the rollback is available.
+     */
+    @Test
+    public void testNativeWatchdogTriggersRollback_Phase2() throws Exception {
+        RollbackManager rm = RollbackUtils.getRollbackManager();
+        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
+                        MODULE_META_DATA_PACKAGE)).isNotNull();
+    }
+
+    /**
+     * Verify the rollback is committed after crashing.
+     */
+    @Test
+    public void testNativeWatchdogTriggersRollback_Phase3() throws Exception {
+        RollbackManager rm = RollbackUtils.getRollbackManager();
+        assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
+                        MODULE_META_DATA_PACKAGE)).isNotNull();
+    }
+
+    @Test
+    public void testNetworkFailedRollback_Phase1() throws Exception {
+        resetNetworkStack();
+    }
+
+    @Test
+    public void testNetworkFailedRollback_Phase2() throws Exception {
+        assertNetworkStackRollbackAvailable();
+    }
+
+    @Test
+    public void testNetworkFailedRollback_Phase3() throws Exception {
+        assertNoNetworkStackRollbackCommitted();
+    }
+
+    @Test
+    public void testNetworkFailedRollback_Phase4() throws Exception {
+        assertNetworkStackRollbackCommitted();
+    }
+
     @Test
     public void assertNetworkStackRollbackAvailable() throws Exception {
         RollbackManager rm = RollbackUtils.getRollbackManager();
@@ -213,20 +249,6 @@
                         getNetworkStackPackageName())).isNull();
     }
 
-    @Test
-    public void assertModuleMetadataRollbackAvailable() throws Exception {
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
-                        MODULE_META_DATA_PACKAGE)).isNotNull();
-    }
-
-    @Test
-    public void assertModuleMetadataRollbackCommitted() throws Exception {
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-        assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
-                        MODULE_META_DATA_PACKAGE)).isNotNull();
-    }
-
     private String getNetworkStackPackageName() {
         Intent intent = new Intent(NETWORK_STACK_CONNECTOR_CLASS);
         ComponentName comp = intent.resolveSystemService(
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index bc98f06..405d998 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -68,35 +68,35 @@
      */
     @Test
     public void testBadApkOnly() throws Exception {
-        runPhase("testBadApkOnlyEnableRollback");
+        runPhase("testBadApkOnly_Phase1");
         getDevice().reboot();
-        runPhase("testBadApkOnlyConfirmEnableRollback");
+        runPhase("testBadApkOnly_Phase2");
         try {
             // This is expected to fail due to the device being rebooted out
             // from underneath the test. If this fails for reasons other than
             // the device reboot, those failures should result in failure of
             // the testApkOnlyConfirmRollback phase.
             CLog.logAndDisplay(LogLevel.INFO, "testBadApkOnlyTriggerRollback is expected to fail");
-            runPhase("testBadApkOnlyTriggerRollback");
+            runPhase("testBadApkOnly_Phase3");
         } catch (AssertionError e) {
             // AssertionError is expected.
         }
 
         getDevice().waitForDeviceAvailable();
 
-        runPhase("testBadApkOnlyConfirmRollback");
+        runPhase("testBadApkOnly_Phase4");
     }
 
     @Test
     public void testNativeWatchdogTriggersRollback() throws Exception {
         //Stage install ModuleMetadata package - this simulates a Mainline module update
-        runPhase("installModuleMetadataPackage");
+        runPhase("testNativeWatchdogTriggersRollback_Phase1");
 
         // Reboot device to activate staged package
         getDevice().reboot();
         getDevice().waitForDeviceAvailable();
 
-        runPhase("assertModuleMetadataRollbackAvailable");
+        runPhase("testNativeWatchdogTriggersRollback_Phase2");
 
         // crash system_server enough times to trigger a rollback
         crashProcess("system_server", NATIVE_CRASHES_THRESHOLD);
@@ -113,7 +113,7 @@
         getDevice().waitForDeviceAvailable();
 
         // verify rollback committed
-        runPhase("assertModuleMetadataRollbackCommitted");
+        runPhase("testNativeWatchdogTriggersRollback_Phase3");
     }
 
     /**
@@ -122,7 +122,7 @@
     @Test
     public void testNetworkFailedRollback() throws Exception {
         // Remove available rollbacks and uninstall NetworkStack on /data/
-        runPhase("resetNetworkStack");
+        runPhase("testNetworkFailedRollback_Phase1");
         // Reduce health check deadline
         getDevice().executeShellCommand("device_config put rollback "
                 + "watchdog_request_timeout_millis 300000");
@@ -137,17 +137,17 @@
         getDevice().waitForDeviceAvailable();
 
         // Verify rollback was enabled
-        runPhase("assertNetworkStackRollbackAvailable");
+        runPhase("testNetworkFailedRollback_Phase2");
 
         // Sleep for < health check deadline
         Thread.sleep(5000);
         // Verify rollback was not executed before health check deadline
-        runPhase("assertNoNetworkStackRollbackCommitted");
+        runPhase("testNetworkFailedRollback_Phase3");
         try {
             // This is expected to fail due to the device being rebooted out
             // from underneath the test. If this fails for reasons other than
             // the device reboot, those failures should result in failure of
-            // the assertNetworkStackExecutedRollback phase.
+            // the testNetworkFailedRollback_Phase4 phase.
             CLog.logAndDisplay(LogLevel.INFO, "Sleep and expect to fail while sleeping");
             // Sleep for > health check deadline
             Thread.sleep(260000);
@@ -157,7 +157,7 @@
 
         getDevice().waitForDeviceAvailable();
         // Verify rollback was executed after health check deadline
-        runPhase("assertNetworkStackRollbackCommitted");
+        runPhase("testNetworkFailedRollback_Phase4");
     }
 
     /**
diff --git a/tests/net/java/android/net/ip/IpServerTest.java b/tests/net/java/android/net/ip/IpServerTest.java
index 05912e8..b6ccebb 100644
--- a/tests/net/java/android/net/ip/IpServerTest.java
+++ b/tests/net/java/android/net/ip/IpServerTest.java
@@ -19,11 +19,13 @@
 import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
 import static android.net.ConnectivityManager.TETHERING_USB;
 import static android.net.ConnectivityManager.TETHERING_WIFI;
+import static android.net.ConnectivityManager.TETHERING_WIFI_P2P;
 import static android.net.ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
 import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
 import static android.net.ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
 import static android.net.ip.IpServer.STATE_AVAILABLE;
+import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
 import static android.net.ip.IpServer.STATE_TETHERED;
 import static android.net.ip.IpServer.STATE_UNAVAILABLE;
 import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
@@ -256,6 +258,23 @@
     }
 
     @Test
+    public void canBeTetheredAsWifiP2p() throws Exception {
+        initStateMachine(TETHERING_WIFI_P2P);
+
+        dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
+        InOrder inOrder = inOrder(mCallback, mNMService);
+        inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME);
+        inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
+        inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
+        inOrder.verify(mCallback).updateInterfaceState(
+                mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
+        inOrder.verify(mCallback).updateLinkProperties(
+                eq(mIpServer), mLinkPropertiesCaptor.capture());
+        assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
+        verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+    }
+
+    @Test
     public void handlesFirstUpstreamChange() throws Exception {
         initTetheredStateMachine(TETHERING_BLUETOOTH, null);
 
@@ -419,6 +438,14 @@
     }
 
     @Test
+    public void startsDhcpServerOnWifiP2p() throws Exception {
+        initTetheredStateMachine(TETHERING_WIFI_P2P, UPSTREAM_IFACE);
+        dispatchTetherConnectionChanged(UPSTREAM_IFACE);
+
+        assertDhcpStarted(new IpPrefix("192.168.49.0/24"));
+    }
+
+    @Test
     public void doesNotStartDhcpServerIfDisabled() throws Exception {
         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */);
         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index c030c3e..5f62c08 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -25,8 +25,10 @@
 import static android.net.ConnectivityManager.EXTRA_AVAILABLE_TETHER;
 import static android.net.ConnectivityManager.TETHERING_USB;
 import static android.net.ConnectivityManager.TETHERING_WIFI;
+import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
 import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
@@ -90,6 +92,9 @@
 import android.net.util.SharedLog;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
+import android.net.wifi.p2p.WifiP2pGroup;
+import android.net.wifi.p2p.WifiP2pInfo;
+import android.net.wifi.p2p.WifiP2pManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.INetworkManagementService;
@@ -140,6 +145,7 @@
     private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
     private static final String TEST_USB_IFNAME = "test_rndis0";
     private static final String TEST_WLAN_IFNAME = "test_wlan0";
+    private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0";
 
     private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
 
@@ -216,9 +222,10 @@
             assertTrue("Non-mocked interface " + ifName,
                     ifName.equals(TEST_USB_IFNAME)
                             || ifName.equals(TEST_WLAN_IFNAME)
-                            || ifName.equals(TEST_MOBILE_IFNAME));
+                            || ifName.equals(TEST_MOBILE_IFNAME)
+                            || ifName.equals(TEST_P2P_IFNAME));
             final String[] ifaces = new String[] {
-                    TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME };
+                    TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME, TEST_P2P_IFNAME};
             return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
                     MacAddress.ALL_ZEROS_ADDRESS);
         }
@@ -361,6 +368,8 @@
                 .thenReturn(new String[] { "test_rndis\\d" });
         when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
                 .thenReturn(new String[]{ "test_wlan\\d" });
+        when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_p2p_regexs))
+                .thenReturn(new String[]{ "test_p2p-p2p\\d-.*" });
         when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
                 .thenReturn(new String[0]);
         when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
@@ -369,7 +378,7 @@
                 .thenReturn(false);
         when(mNMService.listInterfaces())
                 .thenReturn(new String[] {
-                        TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME});
+                        TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME});
         when(mNMService.getInterfaceConfig(anyString()))
                 .thenReturn(new InterfaceConfiguration());
         when(mRouterAdvertisementDaemon.start())
@@ -423,6 +432,31 @@
         mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
+    private static final String[] P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_WIFI_STATE
+    };
+
+    private void sendWifiP2pConnectionChanged(
+            boolean isGroupFormed, boolean isGroupOwner, String ifname) {
+        WifiP2pInfo p2pInfo = new WifiP2pInfo();
+        p2pInfo.groupFormed = isGroupFormed;
+        p2pInfo.isGroupOwner = isGroupOwner;
+
+        NetworkInfo networkInfo = new NetworkInfo(TYPE_WIFI_P2P, 0, null, null);
+
+        WifiP2pGroup group = new WifiP2pGroup();
+        group.setIsGroupOwner(isGroupOwner);
+        group.setInterface(ifname);
+
+        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
+        intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, p2pInfo);
+        intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, networkInfo);
+        intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, group);
+        mServiceContext.sendBroadcastAsUserMultiplePermissions(intent, UserHandle.ALL,
+                P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST);
+    }
+
     private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
         final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
         intent.putExtra(USB_CONNECTED, connected);
@@ -436,11 +470,11 @@
         mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
-    private void verifyInterfaceServingModeStarted() throws Exception {
-        verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME);
+    private void verifyInterfaceServingModeStarted(String ifname) throws Exception {
+        verify(mNMService, times(1)).getInterfaceConfig(ifname);
         verify(mNMService, times(1))
-                .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
-        verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
+                .setInterfaceConfig(eq(ifname), any(InterfaceConfiguration.class));
+        verify(mNMService, times(1)).tetherInterface(ifname);
     }
 
     private void verifyTetheringBroadcast(String ifname, String whichExtra) {
@@ -530,7 +564,7 @@
         sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
         mLooper.dispatchAll();
 
-        verifyInterfaceServingModeStarted();
+        verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
         verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
         verify(mNMService, times(1)).setIpForwardingEnabled(true);
         verify(mNMService, times(1)).startTethering(any(String[].class));
@@ -542,8 +576,9 @@
         verifyNoMoreInteractions(mWifiManager);
         verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
         verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
-        // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
-        assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
+        // This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
+        // and another one is on IpServer.STATE_TETHERED/IpServer.STATE_LOCAL_ONLY.
+        assertEquals(2, mTetheringDependencies.isTetheringSupportedCalls);
 
         // Emulate externally-visible WifiManager effects, when hotspot mode
         // is being torn down.
@@ -552,9 +587,9 @@
         mLooper.dispatchAll();
 
         verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
-        // TODO: Why is {g,s}etInterfaceConfig() called more than once?
-        verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
-        verify(mNMService, atLeastOnce())
+        // {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
+        verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
+        verify(mNMService, times(2))
                 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
         verify(mNMService, times(1)).stopTethering();
         verify(mNMService, times(1)).setIpForwardingEnabled(false);
@@ -770,7 +805,7 @@
         sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
         mLooper.dispatchAll();
 
-        verifyInterfaceServingModeStarted();
+        verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
         verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
         verify(mNMService, times(1)).setIpForwardingEnabled(true);
         verify(mNMService, times(1)).startTethering(any(String[].class));
@@ -785,8 +820,9 @@
         // In tethering mode, in the default configuration, an explicit request
         // for a mobile network is also made.
         verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
-        // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
-        assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
+        // This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
+        // and another one is on IpServer.STATE_TETHERED/IpServer.STATE_LOCAL_ONLY.
+        assertEquals(2, mTetheringDependencies.isTetheringSupportedCalls);
 
         /////
         // We do not currently emulate any upstream being found.
@@ -809,7 +845,7 @@
         mLooper.dispatchAll();
 
         verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
-        // TODO: Why is {g,s}etInterfaceConfig() called more than once?
+        // {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
         verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
         verify(mNMService, atLeastOnce())
                 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
@@ -857,8 +893,9 @@
                 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
         verify(mWifiManager).updateInterfaceIpState(
                 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
-        // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
-        assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
+        // There are 3 state change event:
+        // AVAILABLE -> STATE_TETHERED -> STATE_AVAILABLE.
+        assertEquals(3, mTetheringDependencies.isTetheringSupportedCalls);
         verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
         // This is called, but will throw.
         verify(mNMService, times(1)).setIpForwardingEnabled(true);
@@ -1031,6 +1068,133 @@
         assertEquals(fakeSubId, newConfig.subId);
     }
 
+    private void workingWifiP2pGroupOwner(
+            boolean emulateInterfaceStatusChanged) throws Exception {
+        if (emulateInterfaceStatusChanged) {
+            mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
+        }
+        sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
+        mLooper.dispatchAll();
+
+        verifyInterfaceServingModeStarted(TEST_P2P_IFNAME);
+        verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_AVAILABLE_TETHER);
+        verify(mNMService, times(1)).setIpForwardingEnabled(true);
+        verify(mNMService, times(1)).startTethering(any(String[].class));
+        verifyNoMoreInteractions(mNMService);
+        verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
+        verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
+        // This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
+        // and another one is on IpServer.STATE_TETHERED/IpServer.STATE_LOCAL_ONLY.
+        assertEquals(2, mTetheringDependencies.isTetheringSupportedCalls);
+
+        assertEquals(TETHER_ERROR_NO_ERROR, mTethering.getLastTetherError(TEST_P2P_IFNAME));
+
+        // Emulate externally-visible WifiP2pManager effects, when wifi p2p group
+        // is being removed.
+        sendWifiP2pConnectionChanged(false, true, TEST_P2P_IFNAME);
+        mTethering.interfaceRemoved(TEST_P2P_IFNAME);
+        mLooper.dispatchAll();
+
+        verify(mNMService, times(1)).untetherInterface(TEST_P2P_IFNAME);
+        // {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
+        verify(mNMService, times(2)).getInterfaceConfig(TEST_P2P_IFNAME);
+        verify(mNMService, times(2))
+                .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
+        verify(mNMService, times(1)).stopTethering();
+        verify(mNMService, times(1)).setIpForwardingEnabled(false);
+        verify(mUpstreamNetworkMonitor, never()).getCurrentPreferredUpstream();
+        verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
+        verifyNoMoreInteractions(mNMService);
+        // Asking for the last error after the per-interface state machine
+        // has been reaped yields an unknown interface error.
+        assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
+    }
+
+    private void workingWifiP2pGroupClient(
+            boolean emulateInterfaceStatusChanged) throws Exception {
+        if (emulateInterfaceStatusChanged) {
+            mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
+        }
+        sendWifiP2pConnectionChanged(true, false, TEST_P2P_IFNAME);
+        mLooper.dispatchAll();
+
+        verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
+        verify(mNMService, never())
+                .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
+        verify(mNMService, never()).tetherInterface(TEST_P2P_IFNAME);
+        verify(mNMService, never()).setIpForwardingEnabled(true);
+        verify(mNMService, never()).startTethering(any(String[].class));
+
+        // Emulate externally-visible WifiP2pManager effects, when wifi p2p group
+        // is being removed.
+        sendWifiP2pConnectionChanged(false, false, TEST_P2P_IFNAME);
+        mTethering.interfaceRemoved(TEST_P2P_IFNAME);
+        mLooper.dispatchAll();
+
+        verify(mNMService, never()).untetherInterface(TEST_P2P_IFNAME);
+        verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
+        verify(mNMService, never())
+                .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
+        verify(mNMService, never()).stopTethering();
+        verify(mNMService, never()).setIpForwardingEnabled(false);
+        verifyNoMoreInteractions(mNMService);
+        // Asking for the last error after the per-interface state machine
+        // has been reaped yields an unknown interface error.
+        assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
+    }
+
+    @Test
+    public void workingWifiP2pGroupOwnerWithIfaceChanged() throws Exception {
+        workingWifiP2pGroupOwner(true);
+    }
+
+    @Test
+    public void workingWifiP2pGroupOwnerSansIfaceChanged() throws Exception {
+        workingWifiP2pGroupOwner(false);
+    }
+
+    private void workingWifiP2pGroupOwnerLegacyMode(
+            boolean emulateInterfaceStatusChanged) throws Exception {
+        // change to legacy mode and update tethering information by chaning SIM
+        when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_p2p_regexs))
+                .thenReturn(new String[]{});
+        final int fakeSubId = 1234;
+        mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId);
+
+        if (emulateInterfaceStatusChanged) {
+            mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
+        }
+        sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
+        mLooper.dispatchAll();
+
+        verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
+        verify(mNMService, never())
+                .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
+        verify(mNMService, never()).tetherInterface(TEST_P2P_IFNAME);
+        verify(mNMService, never()).setIpForwardingEnabled(true);
+        verify(mNMService, never()).startTethering(any(String[].class));
+        assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
+    }
+    @Test
+    public void workingWifiP2pGroupOwnerLegacyModeWithIfaceChanged() throws Exception {
+        workingWifiP2pGroupOwnerLegacyMode(true);
+    }
+
+    @Test
+    public void workingWifiP2pGroupOwnerLegacyModeSansIfaceChanged() throws Exception {
+        workingWifiP2pGroupOwnerLegacyMode(false);
+    }
+
+    @Test
+    public void workingWifiP2pGroupClientWithIfaceChanged() throws Exception {
+        workingWifiP2pGroupClient(true);
+    }
+
+    @Test
+    public void workingWifiP2pGroupClientSansIfaceChanged() throws Exception {
+        workingWifiP2pGroupClient(false);
+    }
+
     // TODO: Test that a request for hotspot mode doesn't interfere with an
     // already operating tethering mode interface.
 }
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 05375b0..21386b8 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -787,7 +787,9 @@
 
     // The dynamicRefTable can be null if there are no resources for this asset cookie.
     // This fine.
-    const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie);
+    auto noop_destructor = [](const DynamicRefTable* /*ref_table */) { };
+    auto dynamicRefTable = std::shared_ptr<const DynamicRefTable>(
+        res.getDynamicRefTableForCookie(assetsCookie), noop_destructor);
 
     Asset* asset = NULL;
 
diff --git a/tools/aapt2/format/binary/XmlFlattener_test.cpp b/tools/aapt2/format/binary/XmlFlattener_test.cpp
index 1dac493..c24488b 100644
--- a/tools/aapt2/format/binary/XmlFlattener_test.cpp
+++ b/tools/aapt2/format/binary/XmlFlattener_test.cpp
@@ -226,10 +226,10 @@
   ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
 
   // The tree needs a custom DynamicRefTable since it is not using a standard app ID (0x7f).
-  android::DynamicRefTable dynamic_ref_table;
-  dynamic_ref_table.addMapping(0x80, 0x80);
+  auto dynamic_ref_table = std::make_shared<android::DynamicRefTable>();
+  dynamic_ref_table->addMapping(0x80, 0x80);
 
-  android::ResXMLTree tree(&dynamic_ref_table);
+  auto tree = android::ResXMLTree(std::move(dynamic_ref_table));
   ASSERT_TRUE(Flatten(doc.get(), &tree));
 
   while (tree.next() != android::ResXMLTree::START_TAG) {
diff --git a/tools/codegen/src/com/android/codegen/FieldInfo.kt b/tools/codegen/src/com/android/codegen/FieldInfo.kt
index ba00264..1a7fd6e 100644
--- a/tools/codegen/src/com/android/codegen/FieldInfo.kt
+++ b/tools/codegen/src/com/android/codegen/FieldInfo.kt
@@ -191,7 +191,7 @@
      * Parcel.write* and Parcel.read* method name wildcard values
      */
     val ParcelMethodsSuffix = when {
-        FieldClass in PRIMITIVE_TYPES - "char" - "boolean" +
+        FieldClass in PRIMITIVE_TYPES - "char" - "boolean" + BOXED_PRIMITIVE_TYPES +
                 listOf("String", "CharSequence", "Exception", "Size", "SizeF", "Bundle",
                         "FileDescriptor", "SparseBooleanArray", "SparseIntArray", "SparseArray") ->
             FieldClass
diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt
index 5a95676..431f378 100644
--- a/tools/codegen/src/com/android/codegen/Generators.kt
+++ b/tools/codegen/src/com/android/codegen/Generators.kt
@@ -417,7 +417,7 @@
     if (!isMethodGenerationSuppressed("writeToParcel", Parcel, "int")) {
         +"@Override"
         +GENERATED_MEMBER_HEADER
-        "public void writeToParcel($Parcel dest, int flags)" {
+        "public void writeToParcel(@$NonNull $Parcel dest, int flags)" {
             +"// You can override field parcelling by defining methods like:"
             +"// void parcelFieldName(Parcel dest, int flags) { ... }"
             +""
@@ -473,7 +473,7 @@
         +"/** @hide */"
         +"@SuppressWarnings({\"unchecked\", \"RedundantCast\"})"
         +GENERATED_MEMBER_HEADER
-        "$visibility $ClassName($Parcel in) {" {
+        "$visibility $ClassName(@$NonNull $Parcel in) {" {
             +"// You can override field unparcelling by defining methods like:"
             +"// static FieldType unparcelFieldName(Parcel in) { ... }"
             +""
@@ -598,7 +598,7 @@
             }
 
             +"@Override"
-            "public $ClassName createFromParcel($Parcel in)" {
+            "public $ClassName createFromParcel(@$NonNull $Parcel in)" {
                 +"return new $ClassName(in);"
             }
             rmEmptyLine()
@@ -611,7 +611,7 @@
     if (!isMethodGenerationSuppressed("equals", "Object")) {
         +"@Override"
         +GENERATED_MEMBER_HEADER
-        "public boolean equals(Object o)" {
+        "public boolean equals(@$Nullable Object o)" {
             +"// You can override field equality logic by defining either of the methods like:"
             +"// boolean fieldNameEquals($ClassName other) { ... }"
             +"// boolean fieldNameEquals(FieldType otherValue) { ... }"
@@ -854,6 +854,7 @@
         it.nameAsString == intOrStringDef?.AnnotationName
                 || it.nameAsString in knownNonValidationAnnotations
                 || it in perElementValidations
+                || it.args.any { (_, value) -> value is ArrayInitializerExpr }
     }.forEach { annotation ->
         appendValidateCall(annotation,
                 valueToValidate = if (annotation.nameAsString == Size) sizeExpr else name)
@@ -874,14 +875,7 @@
     val validate = memberRef("com.android.internal.util.AnnotationValidations.validate")
     "$validate(" {
         !"${annotation.nameAsString}.class, null, $valueToValidate"
-        val params = when (annotation) {
-            is MarkerAnnotationExpr -> emptyMap()
-            is SingleMemberAnnotationExpr -> mapOf("value" to annotation.memberValue)
-            is NormalAnnotationExpr ->
-                annotation.pairs.map { it.name.asString() to it.value }.toMap()
-            else -> throw IllegalStateException()
-        }
-        params.forEach { name, value ->
+        annotation.args.forEach { name, value ->
             !",\n\"$name\", $value"
         }
     }
@@ -910,7 +904,7 @@
         usedSpecializationsSet.toList().forEachLastAware { specType, isLast ->
             val SpecType = specType.capitalize()
             val ActionClass = classRef("com.android.internal.util.DataClass.Per${SpecType}FieldAction")
-            +"$ActionClass<$ClassType> action$SpecType${if_(!isLast, ",")}"
+            +"@$NonNull $ActionClass<$ClassType> action$SpecType${if_(!isLast, ",")}"
         }
     }; " {" {
         usedSpecializations.forEachIndexed { i, specType ->
@@ -925,7 +919,7 @@
         +"/** @deprecated May cause boxing allocations - use with caution! */"
         +"@Deprecated"
         +GENERATED_MEMBER_HEADER
-        "void forEachField($PerObjectFieldAction<$ClassType> action)" {
+        "void forEachField(@$NonNull $PerObjectFieldAction<$ClassType> action)" {
             fields.forEachApply {
                 +"action.acceptObject(this, \"$nameLowerCamel\", $name);"
             }
diff --git a/tools/codegen/src/com/android/codegen/InputSignaturesComputation.kt b/tools/codegen/src/com/android/codegen/InputSignaturesComputation.kt
index 24cf469..d6953c0 100644
--- a/tools/codegen/src/com/android/codegen/InputSignaturesComputation.kt
+++ b/tools/codegen/src/com/android/codegen/InputSignaturesComputation.kt
@@ -87,6 +87,14 @@
         is IntegerLiteralExpr -> sb.append(ex.asInt()).append("L")
         is LongLiteralExpr -> sb.append(ex.asLong()).append("L")
         is DoubleLiteralExpr -> sb.append(ex.asDouble())
+        is ArrayInitializerExpr -> {
+            sb.append("{")
+            ex.values.forEachLastAware { arrayElem, isLast ->
+                appendExpr(sb, arrayElem)
+                if (!isLast) sb.append(", ")
+            }
+            sb.append("}")
+        }
         else -> sb.append(ex)
     }
 }
diff --git a/tools/codegen/src/com/android/codegen/Main.kt b/tools/codegen/src/com/android/codegen/Main.kt
index 039f7b2..ce83d3d 100755
--- a/tools/codegen/src/com/android/codegen/Main.kt
+++ b/tools/codegen/src/com/android/codegen/Main.kt
@@ -9,6 +9,7 @@
 const val INDENT_SINGLE = "    "
 
 val PRIMITIVE_TYPES = listOf("byte", "short", "int", "long", "char", "float", "double", "boolean")
+val BOXED_PRIMITIVE_TYPES = PRIMITIVE_TYPES.map { it.capitalize() } - "Int" + "Integer" - "Char" + "Character"
 
 val BUILTIN_SPECIAL_PARCELLINGS = listOf("Pattern")
 
@@ -142,6 +143,10 @@
         //
         // To regenerate run:
         // $ $cliExecutable ${cliArgs.dropLast(1).joinToString("") { "$it " }}$fileEscaped
+        //
+        // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+        //   Settings > Editor > Code Style > Formatter Control
+        //@formatter:off
 
         """
 
diff --git a/tools/codegen/src/com/android/codegen/SharedConstants.kt b/tools/codegen/src/com/android/codegen/SharedConstants.kt
index 47f774f..3eb9e7b 100644
--- a/tools/codegen/src/com/android/codegen/SharedConstants.kt
+++ b/tools/codegen/src/com/android/codegen/SharedConstants.kt
@@ -1,7 +1,7 @@
 package com.android.codegen
 
 const val CODEGEN_NAME = "codegen"
-const val CODEGEN_VERSION = "1.0.7"
+const val CODEGEN_VERSION = "1.0.9"
 
 const val CANONICAL_BUILDER_CLASS = "Builder"
 const val BASE_BUILDER_CLASS = "BaseBuilder"
diff --git a/tools/codegen/src/com/android/codegen/Utils.kt b/tools/codegen/src/com/android/codegen/Utils.kt
index a1f068a..e703397 100644
--- a/tools/codegen/src/com/android/codegen/Utils.kt
+++ b/tools/codegen/src/com/android/codegen/Utils.kt
@@ -1,9 +1,6 @@
 package com.android.codegen
 
-import com.github.javaparser.ast.Modifier
-import com.github.javaparser.ast.expr.AnnotationExpr
-import com.github.javaparser.ast.expr.Expression
-import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr
+import com.github.javaparser.ast.expr.*
 import com.github.javaparser.ast.nodeTypes.NodeWithModifiers
 import java.time.Instant
 import java.time.ZoneId
@@ -88,3 +85,10 @@
 }
 
 fun bitAtExpr(bitIndex: Int) = "0x${java.lang.Long.toHexString(1L shl bitIndex)}"
+
+val AnnotationExpr.args: Map<String, Expression> get() = when (this) {
+    is MarkerAnnotationExpr -> emptyMap()
+    is SingleMemberAnnotationExpr -> mapOf("value" to memberValue)
+    is NormalAnnotationExpr -> pairs.map { it.name.asString() to it.value }.toMap()
+    else -> throw IllegalArgumentException("Unknown annotation expression: $this")
+}
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
index 70ac0be..a8b9839 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
@@ -18,11 +18,14 @@
 
 import com.android.protolog.tool.CommandOptions.Companion.USAGE
 import com.github.javaparser.ParseProblemException
+import com.github.javaparser.ParserConfiguration
 import com.github.javaparser.StaticJavaParser
 import com.github.javaparser.ast.CompilationUnit
 import java.io.File
 import java.io.FileInputStream
 import java.io.FileOutputStream
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
 import java.util.jar.JarOutputStream
 import java.util.zip.ZipEntry
 import kotlin.system.exitProcess
@@ -45,30 +48,38 @@
         val outJar = JarOutputStream(out)
         val processor = ProtoLogCallProcessor(command.protoLogClassNameArg,
                 command.protoLogGroupsClassNameArg, groups)
-        val transformer = SourceTransformer(command.protoLogImplClassNameArg, processor)
 
-        command.javaSourceArgs.forEach { path ->
-            val file = File(path)
-            val text = file.readText()
-            val newPath = path
-            val outSrc = try {
-                val code = tryParse(text, path)
-                if (containsProtoLogText(text, command.protoLogClassNameArg)) {
-                    transformer.processClass(text, newPath, code)
-                } else {
+        val executor = newThreadPool()
+
+        command.javaSourceArgs.map { path ->
+            executor.submitCallable {
+                val transformer = SourceTransformer(command.protoLogImplClassNameArg, processor)
+                val file = File(path)
+                val text = file.readText()
+                val outSrc = try {
+                    val code = tryParse(text, path)
+                    if (containsProtoLogText(text, command.protoLogClassNameArg)) {
+                        transformer.processClass(text, path, code)
+                    } else {
+                        text
+                    }
+                } catch (ex: ParsingException) {
+                    // If we cannot parse this file, skip it (and log why). Compilation will fail
+                    // in a subsequent build step.
+                    println("\n${ex.message}\n")
                     text
                 }
-            } catch (ex: ParsingException) {
-                // If we cannot parse this file, skip it (and log why). Compilation will fail
-                // in a subsequent build step.
-                println("\n${ex.message}\n")
-                text
+                path to outSrc
             }
-            outJar.putNextEntry(ZipEntry(newPath))
+        }.map { future ->
+            val (path, outSrc) = future.get()
+            outJar.putNextEntry(ZipEntry(path))
             outJar.write(outSrc.toByteArray())
             outJar.closeEntry()
         }
 
+        executor.shutdown()
+
         outJar.close()
         out.close()
     }
@@ -92,23 +103,36 @@
         val processor = ProtoLogCallProcessor(command.protoLogClassNameArg,
                 command.protoLogGroupsClassNameArg, groups)
         val builder = ViewerConfigBuilder(processor)
-        command.javaSourceArgs.forEach { path ->
-            val file = File(path)
-            val text = file.readText()
-            if (containsProtoLogText(text, command.protoLogClassNameArg)) {
-                try {
-                    val code = tryParse(text, path)
-                    val pack = if (code.packageDeclaration.isPresent) code.packageDeclaration
-                            .get().nameAsString else ""
-                    val newPath = pack.replace('.', '/') + '/' + file.name
-                    builder.processClass(code, newPath)
-                } catch (ex: ParsingException) {
-                    // If we cannot parse this file, skip it (and log why). Compilation will fail
-                    // in a subsequent build step.
-                    println("\n${ex.message}\n")
+
+        val executor = newThreadPool()
+
+        command.javaSourceArgs.map { path ->
+            executor.submitCallable {
+                val file = File(path)
+                val text = file.readText()
+                if (containsProtoLogText(text, command.protoLogClassNameArg)) {
+                    try {
+                        val code = tryParse(text, path)
+                        val pack = if (code.packageDeclaration.isPresent) code.packageDeclaration
+                                .get().nameAsString else ""
+                        val newPath = pack.replace('.', '/') + '/' + file.name
+                        builder.findLogCalls(code, newPath)
+                    } catch (ex: ParsingException) {
+                        // If we cannot parse this file, skip it (and log why). Compilation will fail
+                        // in a subsequent build step.
+                        println("\n${ex.message}\n")
+                        null
+                    }
+                } else {
+                    null
                 }
             }
+        }.forEach { future ->
+            builder.addLogCalls(future.get() ?: return@forEach)
         }
+
+        executor.shutdown()
+
         val out = FileOutputStream(command.viewerConfigJsonArg)
         out.write(builder.build().toByteArray())
         out.close()
@@ -122,6 +146,11 @@
 
     @JvmStatic
     fun main(args: Array<String>) {
+        StaticJavaParser.setConfiguration(ParserConfiguration().apply {
+            setLanguageLevel(ParserConfiguration.LanguageLevel.RAW)
+            setAttributeComments(false)
+        })
+
         try {
             val command = CommandOptions(args)
             when (command.command) {
@@ -138,3 +167,8 @@
         }
     }
 }
+
+private fun <T> ExecutorService.submitCallable(f: () -> T) = submit(f)
+
+private fun newThreadPool() = Executors.newFixedThreadPool(
+        Runtime.getRuntime().availableProcessors())
diff --git a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
index 00fd038..9a38773 100644
--- a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
@@ -42,7 +42,6 @@
 import com.github.javaparser.ast.type.Type
 import com.github.javaparser.printer.PrettyPrinter
 import com.github.javaparser.printer.PrettyPrinterConfiguration
-import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter
 
 class SourceTransformer(
     protoLogImplClassName: String,
@@ -135,7 +134,8 @@
         // Inline the new statement.
         val printedIfStmt = inlinePrinter.print(ifStmt)
         // Append blank lines to preserve line numbering in file (to allow debugging)
-        val newLines = LexicalPreservingPrinter.print(parentStmt).count { c -> c == '\n' }
+        val parentRange = parentStmt.range.get()
+        val newLines = parentRange.end.line - parentRange.begin.line
         val newStmt = printedIfStmt.substringBeforeLast('}') + ("\n".repeat(newLines)) + '}'
         // pre-workaround code, see explanation below
         /*
@@ -224,9 +224,7 @@
         fileName = path
         processedCode = code.split('\n').toMutableList()
         offsets = IntArray(processedCode.size)
-        LexicalPreservingPrinter.setup(compilationUnit)
         protoLogCallProcessor.process(compilationUnit, this, fileName)
-        // return LexicalPreservingPrinter.print(compilationUnit)
         return processedCode.joinToString("\n")
     }
 }
diff --git a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt
index 941455a..c100826 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt
@@ -23,39 +23,52 @@
 import java.io.StringWriter
 
 class ViewerConfigBuilder(
-    private val protoLogCallVisitor: ProtoLogCallProcessor
-) : ProtoLogCallVisitor {
-    override fun processCall(
-        call: MethodCallExpr,
-        messageString: String,
-        level: LogLevel,
-        group: LogGroup
-    ) {
+    private val processor: ProtoLogCallProcessor
+) {
+    private fun addLogCall(logCall: LogCall, context: ParsingContext) {
+        val group = logCall.logGroup
+        val messageString = logCall.messageString
         if (group.enabled) {
-            val position = fileName
-            val key = CodeUtils.hash(position, messageString, level, group)
+            val key = logCall.key()
             if (statements.containsKey(key)) {
-                if (statements[key] != LogCall(messageString, level, group, position)) {
+                if (statements[key] != logCall) {
                     throw HashCollisionException(
                             "Please modify the log message \"$messageString\" " +
-                                    "or \"${statements[key]}\" - their hashes are equal.",
-                            ParsingContext(fileName, call))
+                                    "or \"${statements[key]}\" - their hashes are equal.", context)
                 }
             } else {
                 groups.add(group)
-                statements[key] = LogCall(messageString, level, group, position)
-                call.range.isPresent
+                statements[key] = logCall
             }
         }
     }
 
     private val statements: MutableMap<Int, LogCall> = mutableMapOf()
     private val groups: MutableSet<LogGroup> = mutableSetOf()
-    private var fileName: String = ""
 
-    fun processClass(unit: CompilationUnit, fileName: String) {
-        this.fileName = fileName
-        protoLogCallVisitor.process(unit, this, fileName)
+    fun findLogCalls(unit: CompilationUnit, fileName: String): List<Pair<LogCall, ParsingContext>> {
+        val calls = mutableListOf<Pair<LogCall, ParsingContext>>()
+        val visitor = object : ProtoLogCallVisitor {
+            override fun processCall(
+                call: MethodCallExpr,
+                messageString: String,
+                level: LogLevel,
+                group: LogGroup
+            ) {
+                val logCall = LogCall(messageString, level, group, fileName)
+                val context = ParsingContext(fileName, call)
+                calls.add(logCall to context)
+            }
+        }
+        processor.process(unit, visitor, fileName)
+
+        return calls
+    }
+
+    fun addLogCalls(calls: List<Pair<LogCall, ParsingContext>>) {
+        calls.forEach { (logCall, context) ->
+            addLogCall(logCall, context)
+        }
     }
 
     fun build(): String {
@@ -101,5 +114,7 @@
         val logLevel: LogLevel,
         val logGroup: LogGroup,
         val position: String
-    )
+    ) {
+        fun key() = CodeUtils.hash(position, messageString, logLevel, logGroup)
+    }
 }
diff --git a/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigBuilderTest.kt b/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigBuilderTest.kt
index 2b6abcd..a24761a 100644
--- a/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigBuilderTest.kt
+++ b/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigBuilderTest.kt
@@ -17,8 +17,7 @@
 package com.android.protolog.tool
 
 import com.android.json.stream.JsonReader
-import com.github.javaparser.ast.CompilationUnit
-import com.github.javaparser.ast.expr.MethodCallExpr
+import com.android.protolog.tool.ViewerConfigBuilder.LogCall
 import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.mockito.Mockito
@@ -34,14 +33,12 @@
         private val GROUP1 = LogGroup("TEST_GROUP", true, true, TAG1)
         private val GROUP2 = LogGroup("DEBUG_GROUP", true, true, TAG2)
         private val GROUP3 = LogGroup("DEBUG_GROUP", true, true, TAG2)
+        private val GROUP_DISABLED = LogGroup("DEBUG_GROUP", false, true, TAG2)
+        private val GROUP_TEXT_DISABLED = LogGroup("DEBUG_GROUP", true, false, TAG2)
         private const val PATH = "/tmp/test.java"
     }
 
-    private val processor: ProtoLogCallProcessor = Mockito.mock(ProtoLogCallProcessor::class.java)
-    private val configBuilder = ViewerConfigBuilder(processor)
-    private val dummyCompilationUnit = CompilationUnit()
-
-    private fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
+    private val configBuilder = ViewerConfigBuilder(Mockito.mock(ProtoLogCallProcessor::class.java))
 
     private fun parseConfig(json: String): Map<Int, ViewerConfigParser.ConfigEntry> {
         return ViewerConfigParser().parseConfig(JsonReader(StringReader(json)))
@@ -49,22 +46,10 @@
 
     @Test
     fun processClass() {
-        Mockito.`when`(processor.process(any(CompilationUnit::class.java),
-                any(ProtoLogCallVisitor::class.java), any(String::class.java)))
-                .thenAnswer { invocation ->
-            val visitor = invocation.arguments[1] as ProtoLogCallVisitor
-
-            visitor.processCall(MethodCallExpr(), TEST1.messageString, LogLevel.INFO,
-                    GROUP1)
-            visitor.processCall(MethodCallExpr(), TEST2.messageString, LogLevel.DEBUG,
-                    GROUP2)
-            visitor.processCall(MethodCallExpr(), TEST3.messageString, LogLevel.ERROR,
-                    GROUP3)
-
-            invocation.arguments[0] as CompilationUnit
-        }
-
-        configBuilder.processClass(dummyCompilationUnit, PATH)
+        configBuilder.addLogCalls(listOf(
+                LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH),
+                LogCall(TEST2.messageString, LogLevel.DEBUG, GROUP2, PATH),
+                LogCall(TEST3.messageString, LogLevel.ERROR, GROUP3, PATH)).withContext())
 
         val parsedConfig = parseConfig(configBuilder.build())
         assertEquals(3, parsedConfig.size)
@@ -78,22 +63,10 @@
 
     @Test
     fun processClass_nonUnique() {
-        Mockito.`when`(processor.process(any(CompilationUnit::class.java),
-                any(ProtoLogCallVisitor::class.java), any(String::class.java)))
-                .thenAnswer { invocation ->
-            val visitor = invocation.arguments[1] as ProtoLogCallVisitor
-
-            visitor.processCall(MethodCallExpr(), TEST1.messageString, LogLevel.INFO,
-                    GROUP1)
-            visitor.processCall(MethodCallExpr(), TEST1.messageString, LogLevel.INFO,
-                    GROUP1)
-            visitor.processCall(MethodCallExpr(), TEST1.messageString, LogLevel.INFO,
-                    GROUP1)
-
-            invocation.arguments[0] as CompilationUnit
-        }
-
-        configBuilder.processClass(dummyCompilationUnit, PATH)
+        configBuilder.addLogCalls(listOf(
+                LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH),
+                LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH),
+                LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH)).withContext())
 
         val parsedConfig = parseConfig(configBuilder.build())
         assertEquals(1, parsedConfig.size)
@@ -103,28 +76,19 @@
 
     @Test
     fun processClass_disabled() {
-        Mockito.`when`(processor.process(any(CompilationUnit::class.java),
-                any(ProtoLogCallVisitor::class.java), any(String::class.java)))
-                .thenAnswer { invocation ->
-            val visitor = invocation.arguments[1] as ProtoLogCallVisitor
-
-            visitor.processCall(MethodCallExpr(), TEST1.messageString, LogLevel.INFO,
-                    GROUP1)
-            visitor.processCall(MethodCallExpr(), TEST2.messageString, LogLevel.DEBUG,
-                    LogGroup("DEBUG_GROUP", false, true, TAG2))
-            visitor.processCall(MethodCallExpr(), TEST3.messageString, LogLevel.ERROR,
-                    LogGroup("DEBUG_GROUP", true, false, TAG2))
-
-            invocation.arguments[0] as CompilationUnit
-        }
-
-        configBuilder.processClass(dummyCompilationUnit, PATH)
+        configBuilder.addLogCalls(listOf(
+                LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH),
+                LogCall(TEST2.messageString, LogLevel.DEBUG, GROUP_DISABLED, PATH),
+                LogCall(TEST3.messageString, LogLevel.ERROR, GROUP_TEXT_DISABLED, PATH))
+                .withContext())
 
         val parsedConfig = parseConfig(configBuilder.build())
         assertEquals(2, parsedConfig.size)
-        assertEquals(TEST1, parsedConfig[CodeUtils.hash(PATH, TEST1.messageString,
-	           LogLevel.INFO, GROUP1)])
-        assertEquals(TEST3, parsedConfig[CodeUtils.hash(PATH, TEST3.messageString,
-	           LogLevel.ERROR, LogGroup("DEBUG_GROUP", true, false, TAG2))])
+        assertEquals(TEST1, parsedConfig[CodeUtils.hash(
+                PATH, TEST1.messageString, LogLevel.INFO, GROUP1)])
+        assertEquals(TEST3, parsedConfig[CodeUtils.hash(
+                PATH, TEST3.messageString, LogLevel.ERROR, GROUP_TEXT_DISABLED)])
     }
+
+    private fun List<LogCall>.withContext() = map { it to ParsingContext() }
 }
diff --git a/tools/streaming_proto/Android.bp b/tools/streaming_proto/Android.bp
index 14eead8..1390f63 100644
--- a/tools/streaming_proto/Android.bp
+++ b/tools/streaming_proto/Android.bp
@@ -29,7 +29,7 @@
         "-Werror",
     ],
 
-    shared_libs: ["libprotoc"],
+    static_libs: ["libprotoc"],
 }
 
 cc_binary_host {
diff --git a/wifi/java/android/net/wifi/IScanResultsListener.aidl b/wifi/java/android/net/wifi/IScanResultsListener.aidl
new file mode 100644
index 0000000..bec74a6
--- /dev/null
+++ b/wifi/java/android/net/wifi/IScanResultsListener.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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 android.net.wifi;
+
+/**
+ * Interface for Wi-Fi scan result available callback.
+ *
+ * @hide
+ */
+oneway interface IScanResultsListener
+{
+    void onScanResultsAvailable();
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index b7e1094..1337739 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -28,6 +28,7 @@
 import android.net.wifi.IDppCallback;
 import android.net.wifi.ILocalOnlyHotspotCallback;
 import android.net.wifi.INetworkRequestMatchCallback;
+import android.net.wifi.IScanResultsListener;
 import android.net.wifi.ISoftApCallback;
 import android.net.wifi.ITrafficStateCallback;
 import android.net.wifi.ITxPacketCountListener;
@@ -227,4 +228,8 @@
     oneway void forget(int netId, in IBinder binder, in IActionListener listener, int callbackIdentifier);
 
     oneway void getTxPacketCount(String packageName, in IBinder binder, in ITxPacketCountListener listener, int callbackIdentifier);
+
+    void registerScanResultsListener(in IBinder binder, in IScanResultsListener Listener, int listenerIdentifier);
+
+    void unregisterScanResultsListener(int listenerIdentifier);
 }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 5496e83..dd9ee3b 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -5104,4 +5104,90 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Base class for scan results listener. Should be implemented by applications and set when
+     * calling {@link WifiManager#addScanResultsListener(Executor, ScanResultsListener)}.
+     */
+    public interface ScanResultsListener {
+
+        /**
+         * Called when new scan results available.
+         * Caller should use {@link WifiManager#getScanResults()} to get the scan results.
+         */
+        void onScanResultsAvailable();
+    }
+
+    private class ScanResultsListenerProxy extends IScanResultsListener.Stub {
+        private final Executor mExecutor;
+        private final ScanResultsListener mListener;
+
+        ScanResultsListenerProxy(Executor executor, ScanResultsListener listener) {
+            mExecutor = executor;
+            mListener = listener;
+        }
+
+        @Override
+        public void onScanResultsAvailable() {
+            mExecutor.execute(mListener::onScanResultsAvailable);
+        }
+    }
+
+    /**
+     * Add a listener for Scan Results. See {@link ScanResultsListener}.
+     * Caller will receive the event when scan results are available.
+     * Caller should use {@link WifiManager#getScanResults()} to get the scan results.
+     * Caller can remove a previously registered listener using
+     * {@link WifiManager#removeScanResultsListener(ScanResultsListener)}
+     * <p>
+     * Applications should have the
+     * {@link android.Manifest.permission#ACCESS_WIFI_STATE} permission. Callers
+     * without the permission will trigger a {@link java.lang.SecurityException}.
+     * <p>
+     *
+     * @param executor  The executor to execute the listener of the {@code listener} object.
+     * @param listener listener for Scan Results events
+     */
+
+    @RequiresPermission(ACCESS_WIFI_STATE)
+    public void addScanResultsListener(@NonNull @CallbackExecutor Executor executor,
+            @NonNull ScanResultsListener listener) {
+        if (listener == null) throw new IllegalArgumentException("listener cannot be null");
+        if (executor == null) throw new IllegalArgumentException("executor cannot be null");
+        Log.v(TAG, "addScanResultsListener: listener=" + listener + ", executor=" + executor);
+        try {
+            IWifiManager iWifiManager = getIWifiManager();
+            if (iWifiManager == null) {
+                throw new RemoteException("Wifi service is not running");
+            }
+            iWifiManager.registerScanResultsListener(
+                    new Binder(),
+                    new ScanResultsListenerProxy(executor, listener),
+                    mContext.getOpPackageName().hashCode());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Allow callers to remove a previously added listener. After calling this method,
+     * applications will no longer receive Scan Results events.
+     *
+     * @param listener listener to remove for Scan Results events
+     */
+    @RequiresPermission(ACCESS_WIFI_STATE)
+    public void removeScanResultsListener(@NonNull ScanResultsListener listener) {
+        if (listener == null) throw new IllegalArgumentException("listener cannot be null");
+        Log.v(TAG, "removeScanResultsListener: listener=" + listener);
+
+        try {
+            IWifiManager iWifiManager = getIWifiManager();
+            if (iWifiManager == null) {
+                throw new RemoteException("Wifi service is not running");
+            }
+            iWifiManager.unregisterScanResultsListener(mContext.getOpPackageName().hashCode());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 4262017..9b529ce 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -23,6 +23,7 @@
 import android.annotation.Nullable;
 import android.app.ActivityThread;
 import android.net.MacAddress;
+import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.Process;
@@ -80,6 +81,10 @@
          */
         private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
         /**
+         * The passpoint config for use with Hotspot 2.0 network
+         */
+        private @Nullable PasspointConfiguration mPasspointConfiguration;
+        /**
          * This is a network that does not broadcast its SSID, so an
          * SSID-specific probe request must be used for scans.
          */
@@ -110,6 +115,7 @@
             mWpa3SaePassphrase = null;
             mWpa2EnterpriseConfig = null;
             mWpa3EnterpriseConfig = null;
+            mPasspointConfiguration = null;
             mIsHiddenSSID = false;
             mIsAppInteractionRequired = false;
             mIsUserInteractionRequired = false;
@@ -234,6 +240,24 @@
         }
 
         /**
+         * Set the associated Passpoint configuration for this network. Needed for authenticating
+         * to Hotspot 2.0 networks. See {@link PasspointConfiguration} for description.
+         *
+         * @param passpointConfig Instance of {@link PasspointConfiguration}.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         * @throws IllegalArgumentException if passpoint configuration is invalid.
+         */
+        public @NonNull Builder setPasspointConfig(
+                @NonNull PasspointConfiguration passpointConfig) {
+            checkNotNull(passpointConfig);
+            if (!passpointConfig.validate()) {
+                throw new IllegalArgumentException("Passpoint configuration is invalid");
+            }
+            mPasspointConfiguration = passpointConfig;
+            return this;
+        }
+
+        /**
          * Specifies whether this represents a hidden network.
          * <p>
          * <li>If not set, defaults to false (i.e not a hidden network).</li>
@@ -366,13 +390,24 @@
             numSecurityTypes += !TextUtils.isEmpty(mWpa3SaePassphrase) ? 1 : 0;
             numSecurityTypes += mWpa2EnterpriseConfig != null ? 1 : 0;
             numSecurityTypes += mWpa3EnterpriseConfig != null ? 1 : 0;
+            numSecurityTypes += mPasspointConfiguration != null ? 1 : 0;
             if (numSecurityTypes > 1) {
                 throw new IllegalStateException("only one of setIsEnhancedOpen, setWpa2Passphrase,"
-                        + "setWpa3Passphrase, setWpa2EnterpriseConfig or setWpa3EnterpriseConfig"
-                        + " can be invoked for network specifier");
+                        + "setWpa3Passphrase, setWpa2EnterpriseConfig, setWpa3EnterpriseConfig"
+                        + "or setPasspointConfig can be invoked for network suggestion");
             }
         }
 
+        private WifiConfiguration buildWifiConfigurationForPasspoint() {
+            WifiConfiguration wifiConfiguration = new WifiConfiguration();
+            wifiConfiguration.FQDN = mPasspointConfiguration.getHomeSp().getFqdn();
+            wifiConfiguration.priority = mPriority;
+            wifiConfiguration.meteredOverride =
+                    mIsMetered ? WifiConfiguration.METERED_OVERRIDE_METERED
+                            : WifiConfiguration.METERED_OVERRIDE_NONE;
+            return wifiConfiguration;
+        }
+
         /**
          * Create a network suggestion object for use in
          * {@link WifiManager#addNetworkSuggestions(List)}.
@@ -384,29 +419,36 @@
          * </p>
          *
          * For example:
-         * To provide credentials for one open, one WPA2 and one WPA3 network with their
-         * corresponding SSID's:
+         * To provide credentials for one open, one WPA2, one WPA3 network with their
+         * corresponding SSID's and one with Passpoint config:
          *
          * <pre>{@code
          * final WifiNetworkSuggestion suggestion1 =
          *      new Builder()
          *      .setSsid("test111111")
-         *      .build()
+         *      .build();
          * final WifiNetworkSuggestion suggestion2 =
          *      new Builder()
          *      .setSsid("test222222")
          *      .setWpa2Passphrase("test123456")
-         *      .build()
+         *      .build();
          * final WifiNetworkSuggestion suggestion3 =
          *      new Builder()
          *      .setSsid("test333333")
          *      .setWpa3Passphrase("test6789")
-         *      .build()
+         *      .build();
+         * final PasspointConfiguration passpointConfig= new PasspointConfiguration();
+         * // configure passpointConfig to include a valid Passpoint configuration
+         * final WifiNetworkSuggestion suggestion4 =
+         *      new Builder()
+         *      .setPasspointConfig(passpointConfig)
+         *      .build();
          * final List<WifiNetworkSuggestion> suggestionsList =
          *      new ArrayList<WifiNetworkSuggestion> { {
          *          add(suggestion1);
          *          add(suggestion2);
          *          add(suggestion3);
+         *          add(suggestion4);
          *      } };
          * final WifiManager wifiManager =
          *      context.getSystemService(Context.WIFI_SERVICE);
@@ -419,21 +461,37 @@
          * @see WifiNetworkSuggestion
          */
         public @NonNull WifiNetworkSuggestion build() {
-            if (mSsid == null) {
-                throw new IllegalStateException("setSsid should be invoked for suggestion");
-            }
-            if (TextUtils.isEmpty(mSsid)) {
-                throw new IllegalStateException("invalid ssid for suggestion");
-            }
-            if (mBssid != null
-                    && (mBssid.equals(MacAddress.BROADCAST_ADDRESS)
-                    || mBssid.equals(MacAddress.ALL_ZEROS_ADDRESS))) {
-                throw new IllegalStateException("invalid bssid for suggestion");
-            }
             validateSecurityParams();
+            WifiConfiguration wifiConfiguration;
+            if (mPasspointConfiguration != null) {
+                if (mSsid != null) {
+                    throw new IllegalStateException("setSsid should not be invoked for suggestion "
+                            + "with Passpoint configuration");
+                }
+                if (mIsHiddenSSID) {
+                    throw new IllegalStateException("setIsHiddenSsid should not be invoked for "
+                            + "suggestion with Passpoint configuration");
+                }
+                wifiConfiguration = buildWifiConfigurationForPasspoint();
+
+            } else {
+                if (mSsid == null) {
+                    throw new IllegalStateException("setSsid should be invoked for suggestion");
+                }
+                if (TextUtils.isEmpty(mSsid)) {
+                    throw new IllegalStateException("invalid ssid for suggestion");
+                }
+                if (mBssid != null
+                        && (mBssid.equals(MacAddress.BROADCAST_ADDRESS)
+                        || mBssid.equals(MacAddress.ALL_ZEROS_ADDRESS))) {
+                    throw new IllegalStateException("invalid bssid for suggestion");
+                }
+                wifiConfiguration = buildWifiConfiguration();
+            }
 
             return new WifiNetworkSuggestion(
-                    buildWifiConfiguration(),
+                    wifiConfiguration,
+                    mPasspointConfiguration,
                     mIsAppInteractionRequired,
                     mIsUserInteractionRequired,
                     Process.myUid(),
@@ -448,6 +506,12 @@
     public final WifiConfiguration wifiConfiguration;
 
     /**
+     * Passpoint configuration for the provided network.
+     * @hide
+     */
+    public final PasspointConfiguration passpointConfiguration;
+
+    /**
      * Whether app needs to log in to captive portal to obtain Internet access.
      * @hide
      */
@@ -474,6 +538,7 @@
     /** @hide */
     public WifiNetworkSuggestion() {
         this.wifiConfiguration = null;
+        this.passpointConfiguration = null;
         this.isAppInteractionRequired = false;
         this.isUserInteractionRequired = false;
         this.suggestorUid = -1;
@@ -481,14 +546,16 @@
     }
 
     /** @hide */
-    public WifiNetworkSuggestion(@NonNull WifiConfiguration wifiConfiguration,
+    public WifiNetworkSuggestion(@NonNull WifiConfiguration networkConfiguration,
+                                 @Nullable PasspointConfiguration passpointConfiguration,
                                  boolean isAppInteractionRequired,
                                  boolean isUserInteractionRequired,
                                  int suggestorUid, @NonNull String suggestorPackageName) {
-        checkNotNull(wifiConfiguration);
+        checkNotNull(networkConfiguration);
         checkNotNull(suggestorPackageName);
+        this.wifiConfiguration = networkConfiguration;
+        this.passpointConfiguration = passpointConfiguration;
 
-        this.wifiConfiguration = wifiConfiguration;
         this.isAppInteractionRequired = isAppInteractionRequired;
         this.isUserInteractionRequired = isUserInteractionRequired;
         this.suggestorUid = suggestorUid;
@@ -501,6 +568,7 @@
                 public WifiNetworkSuggestion createFromParcel(Parcel in) {
                     return new WifiNetworkSuggestion(
                             in.readParcelable(null), // wifiConfiguration
+                            in.readParcelable(null), // PasspointConfiguration
                             in.readBoolean(), // isAppInteractionRequired
                             in.readBoolean(), // isUserInteractionRequired
                             in.readInt(), // suggestorUid
@@ -522,6 +590,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeParcelable(wifiConfiguration, flags);
+        dest.writeParcelable(passpointConfiguration, flags);
         dest.writeBoolean(isAppInteractionRequired);
         dest.writeBoolean(isUserInteractionRequired);
         dest.writeInt(suggestorUid);
@@ -531,7 +600,8 @@
     @Override
     public int hashCode() {
         return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.BSSID,
-                wifiConfiguration.allowedKeyManagement, suggestorUid, suggestorPackageName);
+                wifiConfiguration.allowedKeyManagement, wifiConfiguration.FQDN,
+                suggestorUid, suggestorPackageName);
     }
 
     /**
@@ -546,12 +616,17 @@
             return false;
         }
         WifiNetworkSuggestion lhs = (WifiNetworkSuggestion) obj;
-        return Objects.equals(this.wifiConfiguration.SSID, lhs.wifiConfiguration.SSID)
-                && Objects.equals(this.wifiConfiguration.BSSID, lhs.wifiConfiguration.BSSID)
+        if (this.passpointConfiguration == null ^ lhs.passpointConfiguration == null) {
+            return false;
+        }
+
+        return TextUtils.equals(this.wifiConfiguration.SSID, lhs.wifiConfiguration.SSID)
+                && TextUtils.equals(this.wifiConfiguration.BSSID, lhs.wifiConfiguration.BSSID)
                 && Objects.equals(this.wifiConfiguration.allowedKeyManagement,
-                                  lhs.wifiConfiguration.allowedKeyManagement)
-                && suggestorUid == lhs.suggestorUid
-                && TextUtils.equals(suggestorPackageName, lhs.suggestorPackageName);
+                lhs.wifiConfiguration.allowedKeyManagement)
+                && TextUtils.equals(this.wifiConfiguration.FQDN, lhs.wifiConfiguration.FQDN)
+                && this.suggestorUid == lhs.suggestorUid
+                && TextUtils.equals(this.suggestorPackageName, lhs.suggestorPackageName);
     }
 
     @Override
@@ -559,6 +634,7 @@
         StringBuilder sb = new StringBuilder("WifiNetworkSuggestion [")
                 .append(", SSID=").append(wifiConfiguration.SSID)
                 .append(", BSSID=").append(wifiConfiguration.BSSID)
+                .append(", FQDN=").append(wifiConfiguration.FQDN)
                 .append(", isAppInteractionRequired=").append(isAppInteractionRequired)
                 .append(", isUserInteractionRequired=").append(isUserInteractionRequired)
                 .append(", suggestorUid=").append(suggestorUid)
diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java
index 4ca2a16..94fb5ae 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -26,6 +26,7 @@
 import android.net.wifi.ILocalOnlyHotspotCallback;
 import android.net.wifi.INetworkRequestMatchCallback;
 import android.net.wifi.IOnWifiUsabilityStatsListener;
+import android.net.wifi.IScanResultsListener;
 import android.net.wifi.ISoftApCallback;
 import android.net.wifi.ITrafficStateCallback;
 import android.net.wifi.ITxPacketCountListener;
@@ -515,4 +516,15 @@
             ITxPacketCountListener callback, int callbackIdentifier) {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public void registerScanResultsListener(
+            IBinder binder, IScanResultsListener listener, int listenerIdentifier) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void unregisterScanResultsListener(int listenerIdentifier) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 885139b..f8a0c8f 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -59,6 +59,7 @@
 import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
 import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
 import android.net.wifi.WifiManager.OnWifiUsabilityStatsListener;
+import android.net.wifi.WifiManager.ScanResultsListener;
 import android.net.wifi.WifiManager.SoftApCallback;
 import android.net.wifi.WifiManager.TrafficStateCallback;
 import android.os.Binder;
@@ -102,13 +103,14 @@
     android.net.wifi.IWifiManager mWifiService;
     @Mock ApplicationInfo mApplicationInfo;
     @Mock WifiConfiguration mApConfig;
-    @Mock IBinder mAppBinder;
     @Mock SoftApCallback mSoftApCallback;
     @Mock TrafficStateCallback mTrafficStateCallback;
     @Mock NetworkRequestMatchCallback mNetworkRequestMatchCallback;
     @Mock OnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener;
+    @Mock ScanResultsListener mScanResultListener;
+    @Mock Executor mCallbackExecutor;
+    @Mock Executor mExecutor;
 
-    private Executor mExecutor;
     private Handler mHandler;
     private TestLooper mLooper;
     private WifiManager mWifiManager;
@@ -1711,4 +1713,66 @@
         mLooper.dispatchAll();
         verify(externalListener).onFailure(WifiManager.BUSY);
     }
+
+    /**
+     * Verify an IllegalArgumentException is thrown if listener is not provided.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testAddScanResultsListenerWithNullListener() throws Exception {
+        mWifiManager.addScanResultsListener(mCallbackExecutor, null);
+    }
+
+    /**
+     * Verify an IllegalArgumentException is thrown if executor is not provided.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testAddScanResultsListenerWithNullExecutor() throws Exception {
+        mWifiManager.addScanResultsListener(null, mScanResultListener);
+    }
+
+    /**
+     * Verify client provided listener is being called to the right listener.
+     */
+    @Test
+    public void testAddScanResultsListenerAndReceiveEvent() throws Exception {
+        ArgumentCaptor<IScanResultsListener.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(IScanResultsListener.Stub.class);
+        Executor executor = new SynchronousExecutor();
+        mWifiManager.addScanResultsListener(executor, mScanResultListener);
+        verify(mWifiService).registerScanResultsListener(any(IBinder.class),
+                callbackCaptor.capture(), anyInt());
+        callbackCaptor.getValue().onScanResultsAvailable();
+        verify(mScanResultListener).onScanResultsAvailable();
+    }
+
+    /**
+     * Verify client provided listener is being called on the right executor.
+     */
+    @Test
+    public void testAddScanResultsListenerWithTheTargetExecutor() throws Exception {
+        ArgumentCaptor<IScanResultsListener.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(IScanResultsListener.Stub.class);
+        mWifiManager.addScanResultsListener(mExecutor, mScanResultListener);
+        verify(mWifiService).registerScanResultsListener(any(IBinder.class),
+                callbackCaptor.capture(), anyInt());
+        callbackCaptor.getValue().onScanResultsAvailable();
+        verify(mExecutor).execute(any(Runnable.class));
+    }
+
+    /**
+     * Verify client removeScanResultsListener.
+     */
+    @Test
+    public void testRemoveScanResultsListener() throws Exception {
+        mWifiManager.removeScanResultsListener(mScanResultListener);
+        verify(mWifiService).unregisterScanResultsListener(anyInt());
+    }
+
+    /**
+     * Verify client removeScanResultsListener with null listener will cause an exception.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testRemoveScanResultsListenerWithNullListener() throws Exception {
+        mWifiManager.removeScanResultsListener(null);
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 4dfa96b..6990089 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -19,6 +19,8 @@
 import static org.junit.Assert.*;
 
 import android.net.MacAddress;
+import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.PasspointTestUtils;
 import android.os.Parcel;
 import android.os.Process;
 
@@ -39,6 +41,7 @@
     private static final String TEST_BSSID = "12:12:12:12:12:12";
     private static final String TEST_SSID_1 = "\"Test1234\"";
     private static final String TEST_PRESHARED_KEY = "Test123";
+    private static final String TEST_FQDN = "fqdn";
 
     /**
      * Validate correctness of WifiNetworkSuggestion object created by
@@ -186,6 +189,25 @@
     }
 
     /**
+     * Validate correctness of WifiNetworkSuggestion object created by
+     * {@link WifiNetworkSuggestion.Builder#build()} for Passpoint network which requires
+     *  app interaction and metered.
+     */
+    @Test
+    public void testWifiNetworkSuggestionBuilderForPasspointNetworkWithReqAppInteractionMetered() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration)
+                .setIsAppInteractionRequired(true)
+                .setIsMetered(true)
+                .build();
+        assertEquals(TEST_FQDN, suggestion.wifiConfiguration.FQDN);
+        assertTrue(suggestion.isAppInteractionRequired);
+        assertEquals(suggestion.wifiConfiguration.meteredOverride,
+                WifiConfiguration.METERED_OVERRIDE_METERED);
+    }
+
+    /**
      * Ensure {@link WifiNetworkSuggestion.Builder#setSsid(String)} throws an exception
      * when the string is not Unicode.
      */
@@ -209,6 +231,18 @@
     }
 
     /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)}}
+     * throws an exception when the PasspointConfiguration is not valid.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testWifiNetworkSuggestionBuilderSetPasspointConfigWithNonValid() {
+        PasspointConfiguration passpointConfiguration = new PasspointConfiguration();
+        new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
      * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
      * when {@link WifiNetworkSuggestion.Builder#setSsid(String)} is not set.
      */
@@ -311,6 +345,91 @@
     }
 
     /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setSsid(String)} and
+     * {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothSsidAndPasspointConfig() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setWpa2Passphrase(String)} and
+     * {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothWpa2PassphraseAndPasspointConfig() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        new WifiNetworkSuggestion.Builder()
+                .setWpa2Passphrase(TEST_PRESHARED_KEY)
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setWpa3Passphrase(String)} and
+     * {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothWpa3PassphraseAndPasspointConfig() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        new WifiNetworkSuggestion.Builder()
+                .setWpa3Passphrase(TEST_PRESHARED_KEY)
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setWpa3EnterpriseConfig(WifiEnterpriseConfig)}
+     * and {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} are
+     * invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothEnterpriseAndPasspointConfig() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        new WifiNetworkSuggestion.Builder()
+                .setWpa3EnterpriseConfig(new WifiEnterpriseConfig())
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setIsEnhancedOpen(boolean)} and
+     * {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothEnhancedOpenAndPasspointConfig() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        new WifiNetworkSuggestion.Builder()
+                .setIsEnhancedOpen(true)
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setIsHiddenSsid(boolean)} and
+     * {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothHiddenSsidAndPasspointConfig() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        new WifiNetworkSuggestion.Builder()
+                .setIsHiddenSsid(true)
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
      * Check that parcel marshalling/unmarshalling works
      */
     @Test
@@ -319,8 +438,8 @@
         configuration.SSID = TEST_SSID;
         configuration.BSSID = TEST_BSSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
-        WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, true, TEST_UID, TEST_PACKAGE_NAME);
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion(
+                configuration, null, false, true, TEST_UID, TEST_PACKAGE_NAME);
 
         Parcel parcelW = Parcel.obtain();
         suggestion.writeToParcel(parcelW, 0);
@@ -337,6 +456,39 @@
         // SSID + keyMgmt + same UID). |isAppInteractionRequired| & |isUserInteractionRequired| are
         // not considered for equality and hence needs to be checked for explicitly below.
         assertEquals(suggestion, parcelSuggestion);
+        assertEquals(suggestion.hashCode(), parcelSuggestion.hashCode());
+        assertEquals(suggestion.isAppInteractionRequired,
+                parcelSuggestion.isAppInteractionRequired);
+        assertEquals(suggestion.isUserInteractionRequired,
+                parcelSuggestion.isUserInteractionRequired);
+    }
+
+    /**
+     * Check that parcel marshalling/unmarshalling works
+     */
+    @Test
+    public void testPasspointNetworkSuggestionParcel() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+
+        Parcel parcelW = Parcel.obtain();
+        suggestion.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        WifiNetworkSuggestion parcelSuggestion =
+                WifiNetworkSuggestion.CREATOR.createFromParcel(parcelR);
+
+        // Two suggestion objects are considered equal if they point to the same network (i.e same
+        // SSID + keyMgmt + same UID). |isAppInteractionRequired| & |isUserInteractionRequired| are
+        // not considered for equality and hence needs to be checked for explicitly below.
+        assertEquals(suggestion, parcelSuggestion);
+        assertEquals(suggestion.hashCode(), parcelSuggestion.hashCode());
         assertEquals(suggestion.isAppInteractionRequired,
                 parcelSuggestion.isAppInteractionRequired);
         assertEquals(suggestion.isUserInteractionRequired,
@@ -354,7 +506,7 @@
         configuration.BSSID = TEST_BSSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, true, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration, null, true, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         WifiConfiguration configuration1 = new WifiConfiguration();
@@ -362,10 +514,11 @@
         configuration1.BSSID = TEST_BSSID;
         configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration1, false, true, TEST_UID,
+                new WifiNetworkSuggestion(configuration1, null, false, true, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         assertEquals(suggestion, suggestion1);
+        assertEquals(suggestion.hashCode(), suggestion1.hashCode());
     }
 
     /**
@@ -378,14 +531,14 @@
         configuration.SSID = TEST_SSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration, null, false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         WifiConfiguration configuration1 = new WifiConfiguration();
         configuration1.SSID = TEST_SSID_1;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration1, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration1, null, false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         assertNotEquals(suggestion, suggestion1);
@@ -402,14 +555,14 @@
         configuration.BSSID = TEST_BSSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration, null,  false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         WifiConfiguration configuration1 = new WifiConfiguration();
         configuration1.SSID = TEST_SSID;
         configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration1, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration1, null, false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         assertNotEquals(suggestion, suggestion1);
@@ -425,14 +578,14 @@
         configuration.SSID = TEST_SSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration, null, false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         WifiConfiguration configuration1 = new WifiConfiguration();
         configuration1.SSID = TEST_SSID;
         configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration1, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration1, null, false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         assertNotEquals(suggestion, suggestion1);
@@ -448,11 +601,11 @@
         configuration.SSID = TEST_SSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration, null, false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID_OTHER,
+                new WifiNetworkSuggestion(configuration, null, false, false, TEST_UID_OTHER,
                         TEST_PACKAGE_NAME);
 
         assertNotEquals(suggestion, suggestion1);
@@ -467,13 +620,48 @@
         WifiConfiguration configuration = new WifiConfiguration();
         configuration.SSID = TEST_SSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
-        WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID, TEST_PACKAGE_NAME);
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion(
+                configuration, null, false, false, TEST_UID, TEST_PACKAGE_NAME);
 
-        WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
-                        TEST_PACKAGE_NAME_OTHER);
+        WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion(
+                configuration, null, false, false, TEST_UID, TEST_PACKAGE_NAME_OTHER);
 
         assertNotEquals(suggestion, suggestion1);
     }
+    /**
+     * Check NetworkSuggestion equals returns {@code true} for 2 Passpoint network suggestions with
+     * same FQDN.
+     */
+    @Test
+    public void testPasspointNetworkSuggestionEqualsSameWithSameFQDN() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        PasspointConfiguration passpointConfiguration1 = PasspointTestUtils.createConfig();
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+        WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration1)
+                .build();
+        assertEquals(suggestion, suggestion1);
+        assertEquals(suggestion.hashCode(), suggestion1.hashCode());
+    }
+
+    /**
+     * Check NetworkSuggestion equals returns {@code false} for 2 Passpoint network suggestions with
+     * different FQDN.
+     */
+    @Test
+    public void testPasspointNetworkSuggestionNotEqualsSameWithDifferentFQDN() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        PasspointConfiguration passpointConfiguration1 = PasspointTestUtils.createConfig();
+        passpointConfiguration1.getHomeSp().setFqdn(TEST_FQDN + 1);
+
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+        WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration1)
+                .build();
+        assertNotEquals(suggestion, suggestion1);
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 88740d8..c3b074e 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -19,23 +19,15 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.net.wifi.EAPConstants;
-import android.net.wifi.hotspot2.pps.Credential;
-import android.net.wifi.hotspot2.pps.HomeSp;
-import android.net.wifi.hotspot2.pps.Policy;
-import android.net.wifi.hotspot2.pps.UpdateParameter;
 import android.os.Parcel;
-import android.util.Base64;
 
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 
 import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 /**
@@ -47,136 +39,6 @@
     private static final int CERTIFICATE_FINGERPRINT_BYTES = 32;
 
     /**
-     * Utility function for creating a {@link android.net.wifi.hotspot2.pps.HomeSP}.
-     *
-     * @return {@link android.net.wifi.hotspot2.pps.HomeSP}
-     */
-    private static HomeSp createHomeSp() {
-        HomeSp homeSp = new HomeSp();
-        homeSp.setFqdn("fqdn");
-        homeSp.setFriendlyName("friendly name");
-        homeSp.setRoamingConsortiumOis(new long[] {0x55, 0x66});
-        return homeSp;
-    }
-
-    /**
-     * Utility function for creating a {@link android.net.wifi.hotspot2.pps.Credential}.
-     *
-     * @return {@link android.net.wifi.hotspot2.pps.Credential}
-     */
-    private static Credential createCredential() {
-        Credential cred = new Credential();
-        cred.setRealm("realm");
-        cred.setUserCredential(null);
-        cred.setCertCredential(null);
-        cred.setSimCredential(new Credential.SimCredential());
-        cred.getSimCredential().setImsi("1234*");
-        cred.getSimCredential().setEapType(EAPConstants.EAP_SIM);
-        cred.setCaCertificate(null);
-        cred.setClientCertificateChain(null);
-        cred.setClientPrivateKey(null);
-        return cred;
-    }
-
-    /**
-     * Helper function for creating a {@link Policy} for testing.
-     *
-     * @return {@link Policy}
-     */
-    private static Policy createPolicy() {
-        Policy policy = new Policy();
-        policy.setMinHomeDownlinkBandwidth(123);
-        policy.setMinHomeUplinkBandwidth(345);
-        policy.setMinRoamingDownlinkBandwidth(567);
-        policy.setMinRoamingUplinkBandwidth(789);
-        policy.setMaximumBssLoadValue(12);
-        policy.setExcludedSsidList(new String[] {"ssid1", "ssid2"});
-        HashMap<Integer, String> requiredProtoPortMap = new HashMap<>();
-        requiredProtoPortMap.put(12, "23,342,123");
-        requiredProtoPortMap.put(23, "789,372,1235");
-        policy.setRequiredProtoPortMap(requiredProtoPortMap);
-
-        List<Policy.RoamingPartner> preferredRoamingPartnerList = new ArrayList<>();
-        Policy.RoamingPartner partner1 = new Policy.RoamingPartner();
-        partner1.setFqdn("partner1.com");
-        partner1.setFqdnExactMatch(true);
-        partner1.setPriority(12);
-        partner1.setCountries("us,jp");
-        Policy.RoamingPartner partner2 = new Policy.RoamingPartner();
-        partner2.setFqdn("partner2.com");
-        partner2.setFqdnExactMatch(false);
-        partner2.setPriority(42);
-        partner2.setCountries("ca,fr");
-        preferredRoamingPartnerList.add(partner1);
-        preferredRoamingPartnerList.add(partner2);
-        policy.setPreferredRoamingPartnerList(preferredRoamingPartnerList);
-
-        UpdateParameter policyUpdate = new UpdateParameter();
-        policyUpdate.setUpdateIntervalInMinutes(1712);
-        policyUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM);
-        policyUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP);
-        policyUpdate.setServerUri("policy.update.com");
-        policyUpdate.setUsername("username");
-        policyUpdate.setBase64EncodedPassword(
-                Base64.encodeToString("password".getBytes(), Base64.DEFAULT));
-        policyUpdate.setTrustRootCertUrl("trust.cert.com");
-        policyUpdate.setTrustRootCertSha256Fingerprint(
-                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
-        policy.setPolicyUpdate(policyUpdate);
-
-        return policy;
-    }
-
-    private static UpdateParameter createSubscriptionUpdate() {
-        UpdateParameter subUpdate = new UpdateParameter();
-        subUpdate.setUpdateIntervalInMinutes(9021);
-        subUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_SSP);
-        subUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER);
-        subUpdate.setServerUri("subscription.update.com");
-        subUpdate.setUsername("subUsername");
-        subUpdate.setBase64EncodedPassword(
-                Base64.encodeToString("subPassword".getBytes(), Base64.DEFAULT));
-        subUpdate.setTrustRootCertUrl("subscription.trust.cert.com");
-        subUpdate.setTrustRootCertSha256Fingerprint(new byte[CERTIFICATE_FINGERPRINT_BYTES]);
-        return subUpdate;
-    }
-    /**
-     * Helper function for creating a {@link PasspointConfiguration} for testing.
-     *
-     * @return {@link PasspointConfiguration}
-     */
-    private static PasspointConfiguration createConfig() {
-        PasspointConfiguration config = new PasspointConfiguration();
-        config.setUpdateIdentifier(1234);
-        config.setHomeSp(createHomeSp());
-        config.setAaaServerTrustedNames(
-                new String[] {"trusted.fqdn.com", "another-trusted.fqdn.com"});
-        config.setCredential(createCredential());
-        config.setPolicy(createPolicy());
-        config.setSubscriptionUpdate(createSubscriptionUpdate());
-        Map<String, byte[]> trustRootCertList = new HashMap<>();
-        trustRootCertList.put("trustRoot.cert1.com",
-                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
-        trustRootCertList.put("trustRoot.cert2.com",
-                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
-        config.setTrustRootCertList(trustRootCertList);
-        config.setUpdateIdentifier(1);
-        config.setCredentialPriority(120);
-        config.setSubscriptionCreationTimeInMillis(231200);
-        config.setSubscriptionExpirationTimeInMillis(2134232);
-        config.setSubscriptionType("Gold");
-        config.setUsageLimitUsageTimePeriodInMinutes(3600);
-        config.setUsageLimitStartTimeInMillis(124214213);
-        config.setUsageLimitDataLimit(14121);
-        config.setUsageLimitTimeLimitInMinutes(78912);
-        Map<String, String> friendlyNames = new HashMap<>();
-        friendlyNames.put("en", "ServiceName1");
-        friendlyNames.put("kr", "ServiceName2");
-        config.setServiceFriendlyNames(friendlyNames);
-        return config;
-    }
-
-    /**
      * Verify parcel write and read consistency for the given configuration.
      *
      * @param writeConfig The configuration to verify
@@ -209,7 +71,7 @@
      */
     @Test
     public void verifyParcelWithFullConfiguration() throws Exception {
-        verifyParcel(createConfig());
+        verifyParcel(PasspointTestUtils.createConfig());
     }
 
     /**
@@ -219,7 +81,7 @@
      */
     @Test
     public void verifyParcelWithoutServiceNames() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setServiceFriendlyNames(null);
         verifyParcel(config);
     }
@@ -231,7 +93,7 @@
      */
     @Test
     public void verifyParcelWithoutHomeSP() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setHomeSp(null);
         verifyParcel(config);
     }
@@ -243,7 +105,7 @@
      */
     @Test
     public void verifyParcelWithoutCredential() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setCredential(null);
         verifyParcel(config);
     }
@@ -255,7 +117,7 @@
      */
     @Test
     public void verifyParcelWithoutPolicy() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setPolicy(null);
         verifyParcel(config);
     }
@@ -267,7 +129,7 @@
      */
     @Test
     public void verifyParcelWithoutSubscriptionUpdate() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setSubscriptionUpdate(null);
         verifyParcel(config);
     }
@@ -280,7 +142,7 @@
      */
     @Test
     public void verifyParcelWithoutTrustRootCertList() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setTrustRootCertList(null);
         verifyParcel(config);
     }
@@ -293,7 +155,7 @@
      */
     @Test
     public void verifyParcelWithoutAaaServerTrustedNames() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setAaaServerTrustedNames(null);
         verifyParcel(config);
     }
@@ -318,7 +180,7 @@
      */
     @Test
     public void validateFullConfig() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
 
         assertTrue(config.validate());
         assertTrue(config.validateForR2());
@@ -332,7 +194,7 @@
      */
     @Test
     public void validateFullConfigWithoutUpdateIdentifier() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setUpdateIdentifier(Integer.MIN_VALUE);
 
         assertTrue(config.validate());
@@ -346,7 +208,7 @@
      */
     @Test
     public void validateConfigWithoutCredential() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setCredential(null);
 
         assertFalse(config.validate());
@@ -360,7 +222,7 @@
      */
     @Test
     public void validateConfigWithoutHomeSp() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setHomeSp(null);
 
         assertFalse(config.validate());
@@ -375,7 +237,7 @@
      */
     @Test
     public void validateConfigWithoutPolicy() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setPolicy(null);
 
         assertTrue(config.validate());
@@ -390,7 +252,7 @@
      */
     @Test
     public void validateConfigWithoutSubscriptionUpdate() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setSubscriptionUpdate(null);
 
         assertTrue(config.validate());
@@ -405,7 +267,7 @@
      */
     @Test
     public void validateConfigWithoutAaaServerTrustedNames() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setAaaServerTrustedNames(null);
 
         assertTrue(config.validate());
@@ -420,7 +282,7 @@
      */
     @Test
     public void validateConfigWithInvalidTrustRootCertUrl() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         byte[] rawUrlBytes = new byte[MAX_URL_BYTES + 1];
         Map<String, byte[]> trustRootCertList = new HashMap<>();
         Arrays.fill(rawUrlBytes, (byte) 'a');
@@ -445,7 +307,7 @@
      */
     @Test
     public void validateConfigWithInvalidTrustRootCertFingerprint() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         Map<String, byte[]> trustRootCertList = new HashMap<>();
         trustRootCertList.put("test.cert.com", new byte[CERTIFICATE_FINGERPRINT_BYTES + 1]);
         config.setTrustRootCertList(trustRootCertList);
@@ -482,7 +344,7 @@
      */
     @Test
     public void validateCopyConstructorWithValidSource() throws Exception {
-        PasspointConfiguration sourceConfig = createConfig();
+        PasspointConfiguration sourceConfig = PasspointTestUtils.createConfig();
         PasspointConfiguration copyConfig = new PasspointConfiguration(sourceConfig);
         assertTrue(copyConfig.equals(sourceConfig));
     }
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointTestUtils.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointTestUtils.java
new file mode 100644
index 0000000..adf74eb
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointTestUtils.java
@@ -0,0 +1,163 @@
+/*
+ * 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 android.net.wifi.hotspot2;
+
+import android.net.wifi.EAPConstants;
+import android.net.wifi.hotspot2.pps.Credential;
+import android.net.wifi.hotspot2.pps.HomeSp;
+import android.net.wifi.hotspot2.pps.Policy;
+import android.net.wifi.hotspot2.pps.UpdateParameter;
+import android.util.Base64;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class PasspointTestUtils {
+    private static final int CERTIFICATE_FINGERPRINT_BYTES = 32;
+
+    /**
+     * Utility function for creating a {@link android.net.wifi.hotspot2.pps.HomeSP}.
+     *
+     * @return {@link android.net.wifi.hotspot2.pps.HomeSP}
+     */
+    private static HomeSp createHomeSp() {
+        HomeSp homeSp = new HomeSp();
+        homeSp.setFqdn("fqdn");
+        homeSp.setFriendlyName("friendly name");
+        homeSp.setRoamingConsortiumOis(new long[] {0x55, 0x66});
+        return homeSp;
+    }
+
+    /**
+     * Utility function for creating a {@link android.net.wifi.hotspot2.pps.Credential}.
+     *
+     * @return {@link android.net.wifi.hotspot2.pps.Credential}
+     */
+    private static Credential createCredential() {
+        Credential cred = new Credential();
+        cred.setRealm("realm");
+        cred.setUserCredential(null);
+        cred.setCertCredential(null);
+        cred.setSimCredential(new Credential.SimCredential());
+        cred.getSimCredential().setImsi("1234*");
+        cred.getSimCredential().setEapType(EAPConstants.EAP_SIM);
+        cred.setCaCertificate(null);
+        cred.setClientCertificateChain(null);
+        cred.setClientPrivateKey(null);
+        return cred;
+    }
+
+    /**
+     * Helper function for creating a {@link Policy} for testing.
+     *
+     * @return {@link Policy}
+     */
+    private static Policy createPolicy() {
+        Policy policy = new Policy();
+        policy.setMinHomeDownlinkBandwidth(123);
+        policy.setMinHomeUplinkBandwidth(345);
+        policy.setMinRoamingDownlinkBandwidth(567);
+        policy.setMinRoamingUplinkBandwidth(789);
+        policy.setMaximumBssLoadValue(12);
+        policy.setExcludedSsidList(new String[] {"ssid1", "ssid2"});
+        HashMap<Integer, String> requiredProtoPortMap = new HashMap<>();
+        requiredProtoPortMap.put(12, "23,342,123");
+        requiredProtoPortMap.put(23, "789,372,1235");
+        policy.setRequiredProtoPortMap(requiredProtoPortMap);
+
+        List<Policy.RoamingPartner> preferredRoamingPartnerList = new ArrayList<>();
+        Policy.RoamingPartner partner1 = new Policy.RoamingPartner();
+        partner1.setFqdn("partner1.com");
+        partner1.setFqdnExactMatch(true);
+        partner1.setPriority(12);
+        partner1.setCountries("us,jp");
+        Policy.RoamingPartner partner2 = new Policy.RoamingPartner();
+        partner2.setFqdn("partner2.com");
+        partner2.setFqdnExactMatch(false);
+        partner2.setPriority(42);
+        partner2.setCountries("ca,fr");
+        preferredRoamingPartnerList.add(partner1);
+        preferredRoamingPartnerList.add(partner2);
+        policy.setPreferredRoamingPartnerList(preferredRoamingPartnerList);
+
+        UpdateParameter policyUpdate = new UpdateParameter();
+        policyUpdate.setUpdateIntervalInMinutes(1712);
+        policyUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM);
+        policyUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP);
+        policyUpdate.setServerUri("policy.update.com");
+        policyUpdate.setUsername("username");
+        policyUpdate.setBase64EncodedPassword(
+                Base64.encodeToString("password".getBytes(), Base64.DEFAULT));
+        policyUpdate.setTrustRootCertUrl("trust.cert.com");
+        policyUpdate.setTrustRootCertSha256Fingerprint(
+                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        policy.setPolicyUpdate(policyUpdate);
+
+        return policy;
+    }
+
+    private static UpdateParameter createSubscriptionUpdate() {
+        UpdateParameter subUpdate = new UpdateParameter();
+        subUpdate.setUpdateIntervalInMinutes(9021);
+        subUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_SSP);
+        subUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER);
+        subUpdate.setServerUri("subscription.update.com");
+        subUpdate.setUsername("subUsername");
+        subUpdate.setBase64EncodedPassword(
+                Base64.encodeToString("subPassword".getBytes(), Base64.DEFAULT));
+        subUpdate.setTrustRootCertUrl("subscription.trust.cert.com");
+        subUpdate.setTrustRootCertSha256Fingerprint(new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        return subUpdate;
+    }
+    /**
+     * Helper function for creating a {@link PasspointConfiguration} for testing.
+     *
+     * @return {@link PasspointConfiguration}
+     */
+    public static PasspointConfiguration createConfig() {
+        PasspointConfiguration config = new PasspointConfiguration();
+        config.setUpdateIdentifier(1234);
+        config.setHomeSp(createHomeSp());
+        config.setAaaServerTrustedNames(
+                new String[] {"trusted.fqdn.com", "another-trusted.fqdn.com"});
+        config.setCredential(createCredential());
+        config.setPolicy(createPolicy());
+        config.setSubscriptionUpdate(createSubscriptionUpdate());
+        Map<String, byte[]> trustRootCertList = new HashMap<>();
+        trustRootCertList.put("trustRoot.cert1.com",
+                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        trustRootCertList.put("trustRoot.cert2.com",
+                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        config.setTrustRootCertList(trustRootCertList);
+        config.setUpdateIdentifier(1);
+        config.setCredentialPriority(120);
+        config.setSubscriptionCreationTimeInMillis(231200);
+        config.setSubscriptionExpirationTimeInMillis(2134232);
+        config.setSubscriptionType("Gold");
+        config.setUsageLimitUsageTimePeriodInMinutes(3600);
+        config.setUsageLimitStartTimeInMillis(124214213);
+        config.setUsageLimitDataLimit(14121);
+        config.setUsageLimitTimeLimitInMinutes(78912);
+        Map<String, String> friendlyNames = new HashMap<>();
+        friendlyNames.put("en", "ServiceName1");
+        friendlyNames.put("kr", "ServiceName2");
+        config.setServiceFriendlyNames(friendlyNames);
+        return config;
+    }
+}